My Weblog

Blog about programming and math

State Monads

Finally i got little bit about Haskell monads. There are lot of articles on net but Mike’s World-O-Programming is really excellent . Thanks to Divyanshu for pointing me to the link. Any way i am not going to write another monad tutorial because i am not fit for this topic. I wrote couple of codes using state monads.

import Control.Monad
import Control.Monad.State
import System.Random

--from  wiki books about Haskell
rollDice :: Int -> State StdGen Int 
rollDice n = get >>= ( \s ->  ( return $ randomR ( 1 , n ) s ) >>= ( \ ( v , n ) -> put n >> return v ) )

gcD :: State ( Integer , Integer ) Integer 
gcD = get >>= ( \( a , b ) -> case b == 0 of 
				True -> put ( a , a ) >> return a  --change the state before returning the result  just for fun 
				_    -> put ( b , mod a b ) >> gcD )


fibo :: Int -> State ( Integer , Integer , Int )  Integer 
fibo n = get >>=( \( a , b , t ) -> case t == n of 
					True -> return a 
					_    -> put ( b , a + b , t + 1 ) >> fibo n )
fib :: State ( Integer , Integer ) () 
fib = get >>= ( \( a , b ) -> put ( b , a + b ) ) 

binaryGcd :: State ( Integer , Integer , Int ) Integer 
binaryGcd = get >>=( \( u , v , k ) ->  
			case () of 
			  _ | u == 0 -> return ( v *  2 ^ k  )
			    | v == 0 -> return ( u *  2 ^ k  ) 
			    | and [ even u , even v ] -> put ( div u 2 , div v 2 , succ k ) >> binaryGcd 
			    | and [ even u , odd v ] -> put ( div u 2 , v , k ) >> binaryGcd 
			    | and [ odd u , even v ] -> put ( u , div v 2 , k ) >> binaryGcd 
			    | otherwise -> if u >= v then put ( div ( u - v ) 2 , v , k ) >> binaryGcd 
					    else put ( div ( v - u ) 2 , u , k ) >> binaryGcd  )


findMax :: Int -> State Int () 
findMax n = get >>= ( \x -> case () of 
				_ | x > n -> put ( x ) 
				  | otherwise ->  put ( n )  )


sumList :: [ Integer ] -> State Integer Integer
sumList [] = get >>=(\t -> return t )
sumList ( x : xs ) = 
     get >>= ( \ t -> put ( t + x ) >> sumList xs ) 

sum' :: State ( Integer , Integer ) Integer
sum' = get >>=( \( a , b ) -> return $ a + b ) --here we don't need to change the state 


main = do 
	print $ evalState ( rollDice 1000 ) ( mkStdGen 1000) 
	print $ evalState gcD ( 12345 , 3123123 )
	print $ evalState ( fibo 10 ) ( 0 , 1 , 1 ) -- first two term 0 and 1 and count 0 
	print $ evalState  binaryGcd ( 12345 , 3123123  , 0 )
	print $ execState ( mapM findMax [ 1.. 10 ] ) 0 --remember our maximum value will be kept in state variable
	print $ fst . execState ( replicateM ( 10 - 1 )  fib ) $ ( 0 , 1 )  --to get nth decrase it one [ replicateM ( n - 1 ) fib ]
	print $ evalState ( sumList [ 1..10 ] ) 0
	print $ evalState sum' ( 10 , 100 )  

August 24, 2011 Posted by | Programming | , | 1 Comment

   

Follow

Get every new post delivered to your Inbox.

Join 228 other followers