Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell: Computation "in a monad" -- meaning?

In reading about monads, I keep seeing phrases like "computations in the Xyz monad". What does it mean for a computation to be "in" a certain monad?

I think I have a fair grasp on what monads are about: allowing computations to produce outputs that are usually of some expected type, but can alternatively or additionally convey some other information, such as error status, logging info, state and so on, and allow such computations to be chained.

But I don't get how a computation would be said to be "in" a monad. Does this just refer to a function that produces a monadic result?

Examples: (search "computation in")

  • http://www.haskell.org/tutorial/monads.html
  • http://www.haskell.org/haskellwiki/All_About_Monads
  • http://ertes.de/articles/monads.html
like image 592
gwideman Avatar asked Feb 22 '13 03:02

gwideman


1 Answers

Generally, a "computation in a monad" means not just a function returning a monadic result, but such a function used inside a do block, or as part of the second argument to (>>=), or anything else equivalent to those. The distinction is relevant to something you said in a comment:

"Computation" occurs in func f, after val extracted from input monad, and before result is wrapped as monad. I don't see how the computation per se is "in" the monad; it seems conspicuously "out" of the monad.

This isn't a bad way to think about it--in fact, do notation encourages it because it's a convenient way to look at things--but it does result in a slightly misleading intuition. Nowhere is anything being "extracted" from a monad. To see why, forget about (>>=)--it's a composite operation that exists to support do notation. The more fundamental definition of a monad are three orthogonal functions:

fmap :: (a -> b) -> (m a -> m b)
return :: a -> m a
join :: m (m a) -> m a

...where m is a monad.

Now think about how to implement (>>=) with these: starting with arguments of type m a and a -> m b, your only option is using fmap to get something of type m (m b), after which you can use join to flatten the nested "layers" to get just m b.

In other words, nothing is being taken "out" of the monad--instead, think of the computation as going deeper into the monad, with successive steps being collapsed into a single layer of the monad.

Note that the monad laws are also much simpler from this perspective--essentially, they say that when join is applied doesn't matter as long as the nesting order is preserved (a form of associativity) and that the monadic layer introduced by return does nothing (an identity value for join).

like image 129
C. A. McCann Avatar answered Oct 18 '22 21:10

C. A. McCann