PFP Laboratory 8

From Marek Běhálek Wiki
Jump to navigation Jump to search

Monads

  • Create a type
type SimpleState s a = s -> (s, a)

Implement the monadic functions return and bind

retSt :: a -> SimpleState s a
retSt a = \s -> (s,a)

readInt :: ListInput Int
readInt stateList = (tail stateList, head stateList)

bind :: (s -> (s,a))         -- step
     -> (a -> (s -> (s, b))) -- makeStep
     -> s -> (s, b)          -- (makeStep result) newState
bind step makeStep oldState =
    let (newState, result) = step oldState
    in  (makeStep result) newState
  • Define a new type and a function:
type ListInput a = SimpleState [Int] a

readInt :: ListInput Int
readInt stateList = (tail stateList, head stateList)

Use the previously defined functions to bind actions readInt.

  • Consider you have a type:
newtype State s a = State { runState :: s -> (s, a) }

Make this type the instance of Monad

newtype State s a = State { runState :: s -> (s, a) } 

instance Functor (State s) where
    fmap f m = State $ \s-> let (s',a) = runState m s in (s',f a)

instance Applicative (State s) where
    pure a = State (\s->(s,a))
    f <*> m = State $ \s-> let  (s',f') = runState f s
                                (s'',a) = runState m s' in (s'',f' a)

instance Monad (State s ) where
    return a = State (\s->(s,a))
    m >>= k = State $ \s -> let (s',a) =  runState m s in runState (k a) s'
  • Define a function readInt', so that following code will be valid:
add :: State [Int] Int
add = do x<-readInt'
         y<-readInt'
         return (x+y)
readInt' :: State [Int] Int
readInt' = State {runState = \s->(tail s, head s)}