Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Is a do notation same as chain of responsibility GoF pattern?


Not exactly (although maybe you could implement that pattern with the right choice of monad).

    do
      x <- [1, 2, 3]
      y <- [4, 5, 6]
      return (x + y)
    -- [5, 6, 7,  6, 7, 8,  7, 8, 9]
Here we have a series of assignments followed by an expression computing a result. You can't tell directly, but this is using do-notation in the List monad -- an assignment `x <- [...]` picks a value from the list, then continues. In fact, this code is run once for every possible choice from the given lists, and all of the results are aggregated into a list.

The earlier commenter referred to the Identity monad, which would look like:

    do
      x <- 3
      y <- 5
      return (x + y)
    -- 8
No special lists this time -- what you put on the right is what gets stored in the variable on the left. This is what you're used to in any imperative language.

I suspect `bb` is a little more special, because Ron mentioned it has similarities to LOOP. I'd guess it supports recursive definitions somehow, but it's not clear what the difference actually is.


Curious to know how to implement Do pattern in an OOP language consistently.


Good question. "Do notation" is sometimes referred to as "the programmable semicolon", because how you go from one statement to the next depends on which monad you're in. (In the List example, the assignment `x <- [1, 2, 3]` forked execution three ways before proceeding to the next assignment.)

In Java, the semicolon is pretty much fixed; you can't change the relationship between statements in any meaningful way. So you have to play tricks. You can implement the List example in a crafty but leaky way:

    do(() -> {
      var x = choose(1, 2, 3);
      var y = choose(4, 5, 6);
      return x + y;
    });
When `choose` is called for the first time, it remembers which choice it returns to you. When you `return` from the block, your result is stored, and then the function is re-executed -- except this time, `choose` will now return a different value (the next one). You can implement this in a rather small handful of lines, but it's very tight and clever code, and not at all obvious how it works at first glance.

There's another way to do this, with chained `flatMap` calls, like:

    list(1, 2, 3).flatMap(x ->
      list(4, 5, 6).flatMap(y ->
        list(x + y)));
...but that's so different from "normal" use of a language like Java that readers and writers alike are likely to balk to some extent.


Do isn't a pattern, its a notation for monad operations. Any pattern implementable in it can be reproduced in any language where there are objects which support monad operations by using those operations directly. Some languages (e.g., Scala and its comprehensions, which use monad operations rather than imperative operations over collections the way Python does) also have a do-notation-like syntax sugar, as well.


Monads and 'do' and stuff are just a form of abstract control structure. They're hiding information about the actual nature of a computation, making it look like a bit of imperative code, but in the background they could be doing anything. To be honest, despite the mystique, this isn't so different to virtual calls in an OO language, or just having objects hide their internals. Can you create an algorithm accepting the same steps but performing some magic in the background, around and in between every step? You have decorators, iterators, visitors, all that sort of stuff, so the answer is probably yes. Monads happen to be a very simple way to do this, and so you end up with entire ecosystems and fundamental ways of thinking built on that pattern.


'do' in Haskell is like PROGN right?

I guess in a OOP langague like C++ it would be something like:

foo1(); foo2(); return foo3();

?


progn has a fixed meaning in how to sequence sub expressions

do, afaik, just flips the written expression and use actual bind functions depending on the typeclass at point


i wonder what's the difference between CoF and a sequence of conditionals (except maybe being reified at the application layer and potentially adjusted without changing source, a bit like a macro)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: