Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can I call a monadic function without supplying a monad?

I thought I had a good handle on Haskell Monads until I realized this very simple piece of code made no sense to me (this is from the haskell wiki about the State monad):

playGame :: String -> State GameState GameValue
playGame []     = do
  (_, score) <- get
  return score

What confuses me is, why is the code allowed to call "get", when the only argument supplied is a string? It seems almost like it is pulling the value out of thin air.

A better way for me to ask the question may be, how would one rewrite this function using >>= and lambda's instead of do notation? I'm unable to figure it out myself.

like image 282
parker.sikand Avatar asked Apr 03 '14 15:04

parker.sikand


People also ask

Why do we need monads?

monads are used to address the more general problem of computations (involving state, input/output, backtracking, ...) returning values: they do not solve any input/output-problems directly but rather provide an elegant and flexible abstraction of many solutions to related problems.

What is monadic function?

A monadic function is a function with a single argument, written to its right. It is one of three possible function valences; the other two are dyadic and niladic. The term prefix function is used outside of APL to describe APL's monadic function syntax.

Why is a monad called a monad?

monad, (from Greek monas “unit”), an elementary individual substance that reflects the order of the world and from which material properties are derived. The term was first used by the Pythagoreans as the name of the beginning number of a series, from which all following numbers derived.

Is every monad a functor?

Monads are not a replacement for applicative functors Instead, every monad is an applicative functor (as well as a functor).


1 Answers

Desugaring this into do notation would look like

 playGame [] =
   get >>= \ (_, score) ->
   return score

We could also just write this with fmap

 playGame [] = fmap (\(_, score) -> score) get
 playGame [] = fmap snd get

Now the trick is to realize that get is a value like any other with the type

 State s s

What get will return won't be determined until we feed our computation to runState or similar where we provide an explicit starting value for our state.

If we simplify this further and get rid of the state monad we'd have

playGame :: String -> (GameState -> (GameState, GameValue))
playGame [] = \gamestate -> (gamestate, snd gamestate)

The state monad is just wrapping around all of this manual passing of GameState but you can think of get as accessing the value that our "function" was passed.

like image 177
Daniel Gratzer Avatar answered Oct 27 '22 01:10

Daniel Gratzer