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 )
[...] transformer is way to compose monads simultaneously.Computation of gcd using state monad but what if we want to print value of a and b for each call. Clearly we are looking to compose [...]
Pingback by Monad Transformer « My Weblog | October 21, 2011 |