News for hackers. Stuff that matters.
Re:A Gentle Intro to Monads … Maybe? by Mithaldu on Friday January 17, 2014 @12:45PM (#7077184)
> Typeclasses are a refactoring and abstraction tool used here, but monads are just an abstraction. They exist whether or not you reorganize your code. Even when you're using tuples and the like to implement state you still have a monad, you're just footing the bill on a bunch of complexity to implement it.

I literally have no idea what any of that means. It does not seem in any way to explain why you disagree with my understanding.

For example:

> They exist whether or not you reorganize your code.

This seems like the definition of a non-sequitur to me. Replacing a few words, this sentence reads to me semantically the same as

"Anonymous subroutines exist whether or not you reorganize your code."

A true statement, but not one that conveys any previously unknown meaning.

Also please note that nothing you said addresses the WHY of monads.

Re:A Gentle Intro to Monads … Maybe? by tel on Friday January 17, 2014 @01:25PM (#7077467)
Monads don't have a why. They are simply a common pattern. Typeclasses enable polymorphism in Haskell and polymorphism allows for boilerplate reduction and code reuse. Monads can be factored out using typeclasses and usually are in Haskell. You use monads whether or not you're using Haskell and whether or not your language has built-in state manipulation. Certain types in Haskell are monadic and thus provide examples of functionality which shares that common pattern. Haskell exploits all of this in many ways. First, by tagging effects with types you have better documentation and safer programs. Second, by organizing many distinct types along their common monadic pattern you reduce boilerplate and provide a simple API. Third, by exploiting that API generically you build up a set of language constructs which operate "over all monads" which makes for a powerful construction kit. Fourth, by exploiting some algebraic structure that is a natural consequence of the generic pattern of monads you can decompose and recombine them into what are called transformer stacks.

Monads have no relation whatsoever to boilerplate reduction besides the fact that if you (a) notice their existence and (b) operate in a language with powerful enough generics then you can factor that common pattern to reduce boilerplate using that generics support.

If you recognize monads exist and don't have generics support you can still use the concept to better analyze your code and seek out ways of layering in new effects if desirable. You just won't reduce the boilerplate. This is the case with most languages which implement monads as a library, javascript, ruby, clojure, erlang.

Re:A Gentle Intro to Monads … Maybe? by Mithaldu on Friday January 17, 2014 @01:40PM (#7077584)
Well, since you refuse to use english on a level that can be understood by a reasonably well-taught non-american i can only tell you that while i have heard all the words you use before and understand their individual meanings, i have no idea what those sentences are meant to communicate when put together.

I give up.

Also, quite honestly, your claim that monads have no why makes me strongly question your understanding of the subject matter. Also see Einstein: http://www.brainyquote.com/quotes/quotes/a/alberteins383803....

I thank you for your efforts, but can only ask you to reconsider your approach.

Re:A Gentle Intro to Monads … Maybe? by dllthomas on Friday January 17, 2014 @07:43PM (#7079488)
"If you can't explain it, you don't understand it well enough" doesn't account for people who just suck at explaining.
Re:A Gentle Intro to Monads … Maybe? by dllthomas on Friday January 17, 2014 @07:15PM (#7079401)
There is a few ways you can speak of "the WHY of monads". Most basically, monads are one way of 1) combining things 2) which (may) produce a value, 3) where which things you combine in later may depend on earlier values produced.

Why do we speak of them, as opposed to just combining things in that way when we happen to? Partly, for the reasons people generally speak of design patterns: it's one fewer degree of freedom in your design which makes it easier to reason about and when others know the pattern it is easier to communicate what you are doing to them. In one-off cases, in most languages with (comparatively) limited powers of abstraction, this is most of what's useful about saying "hey, that's a monad!".

In Haskell, "Monad" is also an interface for things that fit that pattern, and we have a lot of functions that operate against that interface to do useful things, so that we don't need to rewrite those things for each new thing that happens to be a monad.

For instance:

    mapM :: Monad m => (a -> m b) -> [a] -> m [b]
which is like map, but takes a function that returns a monadic value instead of any function, and instead of producing a list of those monadic values it stitches together the values and gives you a wrapped list of the values. To drive intuition, we can specialize this for a few individual monads:

    mapM :: (a -> Maybe b) -> [a] -> Maybe [b]
Maybe. Pass it a function that may fail, and a list of values to feed into that function, and it will give you "Just" a list of the results or "Nothing" if any function fails.

    mapM :: (a -> Identity b) -> [a] -> Identity [b]
Identity. As you would pretty much expect, this is isomorphic to map. Not a lot of reason to do this unless you've got some other function you care about which is expecting something of this form and you want to basically pass map.

    mapM :: (a -> [b]) -> [a] -> [[b]]
List. The list monad is for nondeterminism - "take every path". I... don't immediately see a good use for mapM in list - something like concatMap is much more useful - but if you ever have a need for it...

    mapM :: (a -> IO b) -> [a] -> IO [b]
IO. Pass in a function that returns an IO action, and a list of parameters for that function, and give back an IO action that produces a list of the results. A simple example:

    mapM (\ l -> putStr (l ++ ": ") >> fmap (l,) getLine) ["height", "weight"]
This would have the type

    IO [(String, String)]
and would, when executed, prompt the user for height and weight in turn, and return a list of tuples containing both the label and the response. You can see how you could trivially add "age".

    mapM :: (a -> State s b) -> [a] -> State s [b]
State. State actions operate on an additional piece of data that's carried around and threaded through the chain of binds. This specialization of mapM takes a function that produces actions which use or modify state, threads them together into one big such action.

    mapM :: (a -> Parser b) -> [a] -> Parser [b]
Parser, from the wonderful attoparsec. Here, we pass in a function that generates parsers, and a list of inputs to that function, and get a parser that parses a list!

There are a ton more similarly abstract, comparably useful functions, some of which are in http://hackage.haskell.org/package/base-4.6.0.1/docs/Control... - and you can always write something new when there's a pattern you want to exploit for which a combinator doesn't exist. All of this - both the implementations of the monads (except the internals of IO) and the functions that operate on them - is written in ordinary Haskell. You can check out the source on Hackage, if you're curious as to how.

mapM is implemented:

    mapM f as = sequence (map f as)
If we inline sequence, that becomes:

    mapM f as = foldr k (return []) ms
      where
        k m m' = do { x <- m; xs <- m'; return (x:xs) }
We can strip out the do notation:

    mapM f as = foldr k (return []) ms
      where
        k m m' = m >>= (\ x -> m' >>= (\ xs -> return (x:xs)))
where it should be somewhat apparent there's not actually any voodoo.
Re:A Gentle Intro to Monads … Maybe? by samstokes on Saturday January 18, 2014 @05:12PM (#7082461)
Those first three paragraphs were a wonderfully clear summary. Thank you!
Re:A Gentle Intro to Monads … Maybe? by dllthomas on Saturday January 18, 2014 @06:18PM (#7082683)
Thanks!