Difference between revisions of "PFP Laboratory 8"
Jump to navigation
Jump to search
Line 1: | Line 1: | ||
== Monads == | == Monads == | ||
+ | * Create a type | ||
+ | <syntaxhighlight lang="Haskell"> | ||
+ | type SimpleState s a = s -> (s, a) | ||
+ | </syntaxhighlight> | ||
+ | Implement the ''monadic'' functions <code>return</code> and <code>bind</code> | ||
+ | |||
+ | <div class="mw-collapsible mw-collapsed" data-collapsetext="Hide solution" data-expandtext="Show solution"> | ||
+ | <syntaxhighlight lang="Haskell"> | ||
+ | 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 | ||
+ | </syntaxhighlight> | ||
+ | </div> | ||
+ | <div style="clear:both"></div> | ||
+ | |||
+ | * Define a new type and a function: | ||
+ | <syntaxhighlight lang="Haskell"> | ||
+ | type ListInput a = SimpleState [Int] a | ||
+ | |||
+ | readInt :: ListInput Int | ||
+ | readInt stateList = (tail stateList, head stateList) | ||
+ | </syntaxhighlight> | ||
+ | Use the previously defined functions to ''bind'' actions <code>readInt</code>. | ||
* Consider you have a type: | * Consider you have a type: | ||
Line 9: | Line 41: | ||
<div class="mw-collapsible mw-collapsed" data-collapsetext="Hide solution" data-expandtext="Show solution"> | <div class="mw-collapsible mw-collapsed" data-collapsetext="Hide solution" data-expandtext="Show solution"> | ||
<syntaxhighlight lang="Haskell"> | <syntaxhighlight lang="Haskell"> | ||
− | + | 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' | ||
+ | </syntaxhighlight> | ||
+ | </div> | ||
+ | <div style="clear:both"></div> | ||
+ | |||
+ | * Define a function <code>readInt'</code>, so that following code will be valid: | ||
+ | <syntaxhighlight lang="Haskell"> | ||
+ | add :: State [Int] Int | ||
+ | add = do x<-readInt' | ||
+ | y<-readInt' | ||
+ | return (x+y) | ||
+ | </syntaxhighlight> | ||
+ | Make this type the instance of <code>Monad</code> | ||
+ | |||
+ | <div class="mw-collapsible mw-collapsed" data-collapsetext="Hide solution" data-expandtext="Show solution"> | ||
+ | <syntaxhighlight lang="Haskell"> | ||
+ | readInt' :: State [Int] Int | ||
+ | readInt' = State {runState = \s->(tail s, head s)} | ||
</syntaxhighlight> | </syntaxhighlight> | ||
</div> | </div> | ||
<div style="clear:both"></div> | <div style="clear:both"></div> |
Revision as of 08:38, 24 October 2022
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)
Make this type the instance of Monad
readInt' :: State [Int] Int
readInt' = State {runState = \s->(tail s, head s)}