News for hackers. Stuff that matters.
Re:Haskell Concepts in One Sentence by scottmsul on Sunday March 26, 2017 @01:06AM (#13959271)
A monad is any data structure which implements bind. Bind is a higher-order function with two parameters - one is the data structure to be transformed, the other is a function which maps over elements in the data structure. However, unlike a normal map, each result of "bind" sits in its own version of the original data structure, which then have to be combined back into a single data structure. The way in which the data structures are combined is what makes each monad different.

For example, List is a monad. Suppose we had a List of Ints, such as [5,3,4]. If we were to run bind over this list, we would need a function that takes an Int and returns a List of something. We could use "show", the function which converts Ints to Strings (a String is technically a List of Char. Since this is a List, we're good). If we call bind using [5,3,4] and show, we get ["5","3","4"] which are then combined to "534".

We can check with the interpreter (>>= is bind):

Prelude> [5,3,4] >>= show

"534"

Re:Haskell Concepts in One Sentence by xelxebar on Sunday March 26, 2017 @04:43AM (#13959819)
Well, you really do need the full Kleisli triple and commutation laws, otherwise bind becomes just a functor.
Re:Haskell Concepts in One Sentence by scottmsul on Sunday March 26, 2017 @10:43AM (#13961012)
That's not exactly true, since bind and fmap have different types.

fmap :: (Functor f) => f a -> (a -> b) -> f b

bind :: (Monad m) => m a -> (a -> m b) -> m b

Functors simply map elements one-to-one, while monads map elements to new data structures, which have to be combined back to a single data structure.

However, it's good you mention the laws - it's certainly possible to define bind with the correct type but incorrect behavior. An example would be defining the List bind in a way that doesn't concatenate the elements in order.

The following is a really good reference for understanding not just the difference between functors, applicatives, and monads, but also why each is more powerful than the one before it.

https://en.wikibooks.org/wiki/Haskell/Applicative_functors#A...

Re:Haskell Concepts in One Sentence by alok-g on Sunday March 26, 2017 @01:57AM (#13959440)
I haven't read/understood your full comment as yet. I've gotten stuck on the first sentence itself: "A monad refers to a class of data structures which implement bind":

Perhaps you mean that a data structure like a list which implements bind is a monad.

Based on what I am reading in your overall comment, a monad is not a class of data structures which implement bind. I italicized keywords which I found problematic in your first statement, noting that you used refers to, and not is. (It is likely that I am confused, but have been missing a clear definition of a monad like "a monad is ...". If the definition involves more terms needing definitions, a topological sort would help. :-)

Re:Haskell Concepts in One Sentence by mrkgnao on Sunday March 26, 2017 @05:33AM (#13959930)
Well, a monad is parameterized over a type (so Maybe is the monad, not Maybe a -- or State s, Writer w, and so on), so GP could be said to have a point: Monad (with a capital m) is the (type)class of datatypes which do all those things.

But, honestly (my silly rules-lawyering aside), a monad "is" an endofunctor and two particular nice natural transformations that satisfy some coherence conditions. This is at the other extreme of the pedagogical utility/clarity scale, since it is the final (if opaque) answer to any definitional ambiguity.

Functors and applicative functors precede monads in (pretentious cough) modern Haskell pedagogy, as championed by the (thankfully non-pretentious) Learn You A Haskell, as well as the Haskell Wikibook. Reading the relevant chapters is a good start. :)

http://learnyouahaskell.com/

https://en.wikibooks.org/wiki/Haskell

Re:Haskell Concepts in One Sentence by scottmsul on Sunday March 26, 2017 @02:09AM (#13959468)
Thanks, I changed the first sentence, hopefully it's less confusing.
Re:Haskell Concepts in One Sentence by jodooshi on Sunday March 26, 2017 @08:14AM (#13960379)
> monads aren’t actually all that complicated. In fact, most of the experienced functional programmers I’ve met consider them downright simple. It’s just that newcomers often have a really hard time trying to figure out what exactly monads even are... A lot of intermediate-to-advanced functional programmers have taken it upon themselves to write monad tutorials... But for the most part, these tutorials never seem to work.

Why is that? Locked doors, headaches, and intellectual need: https://mkremins.github.io/blog/doors-headaches-intellectual... :-)

Re:Haskell Concepts in One Sentence by kaoD on Sunday March 26, 2017 @10:14AM (#13960866)
The article is spot on. The problem with monads is not the what, is the why. Tutorials often explain the what, which is easy to understand (except where people get creative with similes... "monads are like tuna sausages, but you can build castles with them").

Not having used them, I'm still puzzled at _why_ I would need monads at all.

At this point, tutorials use examples like "like flatMap and Maybe in other languages!" which is even more confusing. Why do I need a monad then, if there are similar constructs in other languages that don't need the understanding of monad? Why the complexity? What do I get from monads?

Re:Haskell Concepts in One Sentence by beala on Sunday March 26, 2017 @12:20PM (#13961491)
Monad, like any interface, is useful because we can abstract over it. Let's take an example from Java: both ArrayList and LinkedList implement List. This means I can write code that is agnostic to the implementation of List, and later I can drop in any implementation I want. Seen from the other direction: if I write something that resembles a list and I implement the List interface, all of the code that's compatible with List will also be compatible with my new implementation.

Similarly, if I define a new data type, and realize that it can implement Monad (or more precisely: that it has a monad instance), then I'll be rewarded with a giant library of code that's already compatible with my new data type [1]. Monad is an especially interesting interface because (1) it turns out many things conform to it [2] and (2) it comes with a set of algebraic laws. There is some controversy over how strict we need to be about the algebraic laws, but in some sense the algebraic laws are part of why such a general interface can be meaningful at all.

So yes, it's true that Monad allows us to sequence effects in a lazy pure language, and that's important, but I think a more down to earth reason to be interested is that it allows for more code reuse [3].

[1] Some of the function defined in the standard library: https://hackage.haskell.org/package/base-4.9.1.0/docs/Contro...

[2] See the 'instances' section here: https://hackage.haskell.org/package/base-4.9.1.0/docs/Contro... These are just the instances in the standard library.

[3] It's also worth mentioning that Monad gets all the attention, but Haskell if flush with other mathematically inspired interfaces that are just as general.

Re:Haskell Concepts in One Sentence by eastWestMath on Sunday March 26, 2017 @12:17PM (#13961472)
>At this point, tutorials use examples like "like flatMap and Maybe in other languages!" which is even more confusing. Why do I need a monad then, if there are similar constructs in other languages that don't need the understanding of monad? Why the complexity? What do I get from monads?

Monads are a mathematical concept, like a ring. "Maybe" is a monad in whatever language you use it in, just like integers are a ring in whatever language you use them in. Pointing out that complex numbers, rational numbers, nxn matrices are all examples of rings and wrapping everything up into a type class doesn't add to the complexity of the language.

Re:Haskell Concepts in One Sentence by ebola1717 on Sunday March 26, 2017 @12:41PM (#13961612)
The 'why' question is my pet peeve too - often because the answer to

> Why do I need a monad then, if there are similar constructs in other languages that don't need the understanding of monad?

is that you usually don't.

Where I work, people use a handful of monads daily, but most people know the monad laws, nor do they need to.

But now that they know a few specific monads, the "why" of monads is really, well, we needed certain convenience methods (namely bind aka flatMap) to make using e.g. Maybe or promises not a huge pain. And we chose a uniform way to do it across different wrapper types, so that we minimize the cognitive overhead.

Re:Haskell Concepts in One Sentence by dack on Sunday March 26, 2017 @10:30AM (#13960939)
It lets you model sequential operation and side effects in a pure functional language. You can usually write your code "manually" without monads, and see what it's like. For example, the State monad is basically a function that takes in a value and some state, and returns a new value and a new state. That's a pure function, but composing/chaining them together is pretty messy. If you do that manually once, you'll then get some intuition why the State monad is useful. Then you can expand to other types of monads and eventually have an intuition for their general value.
Re:Haskell Concepts in One Sentence by taesis on Sunday March 26, 2017 @11:37AM (#13961289)
Edit: You don't really need monads any more than you need classes, interfaces, functions, procedures (just use goto!), etc. they just help bring a bunch of seemingly disparate functionality together into one standard (which is helpful in, e.g. Scala or Haskell where there's some syntactic sugar for dealing with monads). People complained for the longest time (amongst many, many other things) that Javascript lacked classes, even though you could totally hack it together with `new`, functions and prototypes. Similarly, FP people complain that everything else lacks monad support, even though they can hack it together with largely language independent features (typically without compile-time checking).

I don't have an intuitive grasp of the formal definition of monads, but some examples of things that I _think_ are monads (in Java ... sorry :/ it's all I work with these days):

* jOOQ [1]: you use it to build up a sequence of SQL statements with a pleasant chaining API, then execute the whole shebang * Promise/future chaining: you build up a sequence of promises that should apply in-order, then defer their execution until later (unless you use a language that performs a transformation at compile time which effectively does this for you). * Streams/optional mapping: you build up a sequence of functions that should apply in-order to every element in a potentially empty sequence (optional: a sequence of 0 or 1). * The builder pattern: you build up a sequence of property values, then (potentially) construct the entire object.

[1]: https://www.jooq.org/

Re:Haskell Concepts in One Sentence by louthy on Sunday March 26, 2017 @02:57PM (#13962431)
> Why do I need a monad then, if there are similar constructs in other languages that don't need the understanding of monad? Why the complexity? What do I get from monads?

They remove the need to type the same shit over and over again. With a list monad you avoid having to write the loop constructs, for the Option/Maybe monad (optional value) you avoid having to write if/then/else, for the Either/Choice monad you avoid having to write if/then/else and manually propagating an error value on failure, for the State monad you avoid having to pass a context value through as an argument to every function, for the Try monad you get exception handling and error propagation like the Either/Choice monad, with the Writer monad you are able to do logging without a global logging system or having to manually pass through a logging context, etc.

Ultimately they're there to reduce boilerplate and to help write more composable and reliable code. There are other benefits, but this encapsulation and abstraction of common patterns is what most programmers strive for, no matter what language they use, so I feel it's important to put them in that context.

Let me give you a very simple example. I'm going to use C# because it's been a long time since I've done any Haskell and I'll probably get it wrong.

I'm going to create a monad called NoNull. If at any point it sees a value that is null then it will stop the computation and return without completing. It's a slightly pointless example because C# has the null propagating operator, but conceptually it should be easy for any programmer to grasp that using null is bad, so being able to 'early out' of a computation when you get a null value is desirable.

First I'll define the type:

    public class NoNull<A> where A : class
    {
        public readonly A Value;

        public NoNull(A value) =>
            Value = value;

        public static NoNull<A> Return(A value) =>
            new NoNull<A>(value);

        public NoNull<B> Bind<B>(Func<A, NoNull<B>> bind) where B : class =>
            Value is null
                ? NoNull<B>.Return(null)
                : bind(Value);

        public NoNull<B> Select<B>(Func<A, B> map) where B : class =>
            Bind(a => NoNull<B>.Return(map(a)));

        public NoNull<C> SelectMany<B, C>(Func<A, NoNull<B>> bind, Func<A, B, C> project) 
            where B : class 
            where C : class =>
                Bind(bind).Select(b => project(Value, b));

    }
It's a class that has a single field called Value. The two functions to care about are:

    Return - Which constructs the NoNull monad
    Bind - Which is the guts of the monad, bind does the work
Select and SelectMany are there to make it work with LINQ. I have implemented them in terms of Bind.

As you can probably see Bind is encapsulating the test for null, and if null is found then the result is Return(null), it doesn't run the `bind` delegate.

Next we'll create some NoNull monadic strings:

    var w = NoNull<string>.Return("hello");
    var x = NoNull<string>.Return(", ");
    var y = NoNull<string>.Return("world");
    var z = NoNull<string>.Return(null);
The last one contains null, the bad value.

I can now use those values like so:

     var result = from a in w
                  from b in x
                  from c in y
                  select a + b + c;
Notice there's no checks for null, the monad does that work for us.

In this instance, result.Value is equal to "hello, world".

Now if I inject a bad value into our monadic computation:

    var result = from a in w
                 from b in x
                 from c in y
                 from d in z             // <--- this is null
                 select a + b + c + d;
Then result.Value is equal to null and the `a + b + c + d` didn't run at all.

The alternative is this:

    string w = "hello";
    string x = ", ";
    string y = "world";
    string z = null;

    string result = null;
    if (w != null)
    {
        if (x != null)
        {
            if (y != null)
            {
                if (z != null)
                {
                    result = w + x + y + z;
                }
            }
        }
    }
Where the programmer constantly has to do the work that the monad will do for free. I've nested those if statements to try and give you the impression of what the series of 'from' expressions are in the example above (in Haskell it's known as 'do notation'). Each 'from' creates a context over the whole of the rest of the expression.

For the avoidance of doubt about the nesting, I could have written it thus:

    var result = w.Bind(a =>
                 x.Bind(b =>
                 y.Bind(c =>
                 z.Bind(d =>
                 NoNull<string>.Return(a + b + c + d)))));

Here [1] is an example of a Parser monad in action in C# (it's part of a parser that parses C# source that I use to generate API reference docs for my github projects [2]). This runs code 'in the gaps' between each 'from' statement. What it does in those gaps is check if the parser above it failed, and if so it bails out with an appropriate error message based on what it expected. But you don't see any if(result.IsFaulted) ... code anywhere, or maintenance of the position of the parser in the input stream, because that is encapsulated in the Parser monad. It makes the code very clear (I think) in that it's not cluttered with the regular scaffolding of control structures that you usually see in imperative languages.

What's really quite beautiful about monads is the way they compose, and I think this is especially beautiful with parser combinators. A Parser<Char> which parses a single character has the same interface as a Parser<SourceFile> which parses an entire source file. Being able to build simple parsers and then combine them into more complex ones is just a joy to do. Clearly parsing isn't unique to monads, but there's an elegance to it (and monads in general) which I think is hard to resist.

[1] https://github.com/louthy/best-form/blob/master/bestform.cs/...

[2] https://louthy.github.io/language-ext/LanguageExt.Core/Langu...

Re:Haskell Concepts in One Sentence by jejones3141 on Sunday March 26, 2017 @11:37AM (#13961291)
The Monad Challenges are, I think, set up to give you the needed headache. They're helping me, that's for sure. http://mightybyte.github.io/monad-challenges/
Re:Haskell Concepts in One Sentence by norswap on Sunday March 26, 2017 @08:27AM (#13960421)
A monad is a "value" of a type X that depends on a type T: X[T]. It must have a "way" to take a function T -> X[T] and apply it to itself so as to get another X[T].

Usually that "way" is a function called "bind" with signature:

    (X[T], (T -> X[T]) -> X[T]
And that's really all there is to it.

Monads are fundamental only in the sense that there happens to be a lot of things for which these structures are useful (lists, optionals, effect wrappers, ...).

Re:Haskell Concepts in One Sentence by jnordwick on Sunday March 26, 2017 @01:27AM (#13959339)
> each result of "bind" sits in its own version of the original data structure, which then have to be combined back into a single data structure

That doesn't make sense to me. Let's say I have the list [5,3,4], to me that means each application returns a three element list [f(5),x,x], [x,f(3),x], and [x,x,f(4)] then the bind function takes these lists and turns them into [f(5),f(3),f(4)].

What makes this function a monad?

Re:Haskell Concepts in One Sentence by Tarean on Sunday March 26, 2017 @04:44AM (#13959823)
I think an easier to understand definition uses fmap and join. Example:

    f x = [x, x*2]

    f =<< [5, 3, 4]
    join (fmap f [5, 3, 4])
    join ([[5, 10], [3, 6], [4, 8]])
    [5, 10, 3, 6, 4, 8]
So the pattern is fmap a function `a -> f b`; this leaves us with `f (f b)` so we flatten. You might notice that we could bind as often as we want since we always get a list of integers!
Re:Haskell Concepts in One Sentence by StavrosK on Sunday March 26, 2017 @05:09AM (#13959879)
I think if you already know fmap, join and Haskell syntax, you also already know monads, so I'm not sure whom this is easier for :P
Re:Haskell Concepts in One Sentence by gizmo686 on Sunday March 26, 2017 @01:40AM (#13959377)
In this case "data structure" refers to List, not a specific size or type of list.

For example, suppose you have a list of ints, and want to bind a function, show. We have types:

  [5,3,4] :: List Int
  show :: Int -> List Char
That is to say, [5,3,4] is a list of ints, and show is a function that takes an int and returns a list of characters.

In this case, we would have

  [5,3,4] >>= show
  f(5) ++ f(3) ++ f(4)
  ['5'] ++ ['3'] ++ ['4']
  ['5','3','4']
where "++" is list concatenation. The idea here is that when we apply show, we get back 3 different Lists, and want to combine them into a single list.
Re:Haskell Concepts in One Sentence by jnordwick on Sunday March 26, 2017 @02:30AM (#13959530)
So bind is flat map in other languages? If join is a function that take a list and appends its elements together join ( [[1], [2], [3]] ) -> [1,2,3]

then bind is join(map(f, x))?

bind just seems like a terrible name.

For some reason Haskell users try to make things sounds as academic as possible.

Re:Haskell Concepts in One Sentence by gizmo686 on Sunday March 26, 2017 @03:16AM (#13959625)
>For some reason Haskell users try to make things sounds as academic as possible.

Probably because Haskell ended up being the language for academics. If you want to do programming language research in an ML-type language use Haskell. If you want to make a product, use OCaml. Not entirely true, but pretty close.

>So bind is flat map in other languages.

In the case of a List, yes, but there are other datastructures that implement Monad. This type of thing happens a fair amount in Haskell. It is not that uncommon to see code like:

    instance Monad List where
        (>>=) = flatMap
That is to say, the implementation of the interface is just another function that has a more domain specific name.

There are other monads with a bind that cannot be understood as flatMap.

For example, the Maybe datatype is Haskell's version of Optional. For example, if a variable is of type `Maybe t`, it either contains a single value of type t, or no value. It is common to use Maybe without using it as a monad. However, Maybe does implement the Monad interface. In this case, bind is defined as follows:

    x.bind(f) =
      if (x.hasValue()) then { return Just(f(x.value)) }
      else { return Nothing() }
where Just and Nothing are two constructors of Maybe. If we view 'no value' as analogous to null, then this bind function is null propogation.
Re:Haskell Concepts in One Sentence by Forlien on Sunday March 26, 2017 @04:20AM (#13959766)
I feel a bit dumb asking this, but your explanation doesn't make it clear to me why you can't think of a bind on Maybe as a flatMap on a List with 0 (Nothing) or 1 (Just) elements. Could you elaborate further on how thinking of a bind on Maybe as null propagation eliminates it also being interpreted as a flatMap on a restricted-size list?
Re:Haskell Concepts in One Sentence by fmap on Sunday March 26, 2017 @04:43AM (#13959818)
You're right, maybe is equivalent to the type of lists with at most one element. There are however monad instances which are genuinely different.

For example the state monad is defined as

  F(X) = S -> S*X
I.e., a value of type F(X) is a state transformer which takes a state argument of type S and produces the new state and a value of type X. In this case, bind is sequencing of state transformers.

Using the state monad you can write code that looks like it uses a global variable of type S, while being completely pure which makes testing and refactoring easier, and of course doesn't pollute the rest of the program.

Re:Haskell Concepts in One Sentence by acomar on Monday March 27, 2017 @03:35PM (#13970934)
Unfortunately, not all monads are list-like (though there are a lot that are). The most notorious example is probably Cont[1], the monad of delimited continuations. State, ST, and IO all struggle to be interpreted as lists as well.

[1]: http://blog.sigfpe.com/2008/12/mother-of-all-monads.html

Re:Haskell Concepts in One Sentence by tomsmeding on Sunday March 26, 2017 @03:18AM (#13959631)
Bind is flatmap in the case of lists. Bind is way more generic than just the list monad, and the name "flatmap" doesn't apply to most other monads -- most of which are not List.
Re:Haskell Concepts in One Sentence by aninhumer on Sunday March 26, 2017 @04:40AM (#13959813)
Yes, bind is just flatMap.

Various people seem to be arguing that "flatMap" only makes sense for Lists and similar containers, but I don't really see why. Yes, you have to broaden your notion of "flattening" to understand it, but I think that's a lot easier for people to learn than a "new" operation called "bind".

I've been using Scala for a while after learning Haskell first (and understanding monads), and I've noticed how much more easily people understand flatMap, even for e.g. Futures.

Re:Haskell Concepts in One Sentence by chousuke on Sunday March 26, 2017 @06:02AM (#13959992)
Maybe it's just a difference of perspective, but I do not understand what is so intuitive about flatMap that makes it "easier". The name does not fully capture the idea of bind and requires mental gymnastics to apply to less concrete usecases, whereas bind is not so restricting, while still referring to the use of the abstraction as "glue" and hinting at its relation to composition.
Re:Haskell Concepts in One Sentence by aninhumer on Sunday March 26, 2017 @06:23AM (#13960045)
I think the thing that makes it more intuitive is that it's really easy to see how "flatMap" relates to "flatten" and "map", whereas it's not immediately obvious how "bind" relates to "join" and "map".

And I think expanding a concept which someone already comfortably understands is a lot easier than asking them to learn a new one, even if you say it's kind of similar.

And FWIW, I don't think "flatten" is particularly unintuitive name, even for the more abstract cases, because it's still f (f a) -> f a. The mental gymnastics here is understanding how a Functor can be more than just a container, and you kind of need to learn that anyway.

Re:Haskell Concepts in One Sentence by imh on Sunday March 26, 2017 @06:33AM (#13960068)
Bind is a great name. When you have a function that takes a monadic value of type `m a` (e.g. List[A_] in scala I think) it becomes convenient to program with lambda functions. For list comprehension, you can program like this (python notation now, since everyone reads it):

    bind(list_of_xs, lambda x:
    bind(list_of_ys, lambda y:
    return(x+y)))
That's a list comprehension. You bind the monadic values (list_of_xs) to element values (x). On lines 2 and 3, you can think of x as a bound variable that was assigned to one of the elements of list_of_xs on line 1. Then we "assign" y on line 2, and it's in scope on line 3. "Assign" would have also been a decent name for it. It's way more intuitive for me to think of those three lines as assigning/binding x and y to be summed together, rather than thinking of one flatmap of a lambda to flatmap of a final lambda to a function. The abstraction of variable binding just fits.
Re:Haskell Concepts in One Sentence by jnordwick on Wednesday March 29, 2017 @06:22PM (#13991185)
This isn't even close to being clear.
Re:Haskell Concepts in One Sentence by scottmsul on Sunday March 26, 2017 @01:34AM (#13959359)
It makes a List of Lists, then combines those into a List.

[5,3,4] becomes [f(5), f(3), f(4)], but f(x) must return a List. Those inner Lists are then concatenated.

When I say "original data structure", I mean the type of data structure is the same (in this case, List).

Re:Haskell Concepts in One Sentence by jnordwick on Sunday March 26, 2017 @02:31AM (#13959532)
What is the data structures don't support a join operation, like a tree?
Re:Haskell Concepts in One Sentence by scottmsul on Sunday March 26, 2017 @02:45AM (#13959558)
We would need a way to transform a Tree of Trees into a single Tree. The inner Trees would be at leaf nodes of the outer Tree, so they could be attached in place.

Although I recall monads need to satisfy certain laws, and I don't recall if Trees satisfy them or not. Just because something is a data structure does not necessarily imply it is a monad.

Re:Haskell Concepts in One Sentence by dllthomas on Monday March 27, 2017 @09:27PM (#13973240)
A rose tree is a monad.