4 ms·
Hm. Not really convinced by either Ruby counter-example. The first one's ok, ish, but doesn't take advantage of the fact you can pass a block to `zip` so you d
by regularfry 3y ago
Hm. Not really convinced by either Ruby counter-example. The first one's ok, ish, but doesn't take advantage of the fact you can pass a block to `zip` so you don't need the `map` call.
The second one's just wrong. You wouldn't use `flat_map` for that if you didn't want indentation, you'd use `Enumerator#product`:
def all_flavors
flavors = [:vanilla, :chocolate, :strawberry]
containers = [:cone, :cup]
toppings = [:sprinkles, :nuts, :fudge]
flavors.product(containers, toppings).map { |flavor, container, topping|
["a #{container} of #{flavor} ice cream with #{topping} on top"]
}
end
While that's not quite doing the same as what `pure` and `<>` do in the Haskell example, the complaint was in terms of visual layout and in that respect it's very similar.
- Tainnor 3y agoThe point is that Haskell's do notation works for every monad, whereas "product" in Ruby works for just a cartesian product of sets, and not any other use of monads (e.g. generating random values, async code, operations that might return errors, IO operations, and so on).
- asplake 3y agoTo me the ‘product’ in the Ruby example above is helpfully explicit and could be changed for something else.
- regularfry 3y agoThe point is more specific than that: the claim here against this example is that Haskell's `do` notation uniquely lets you avoid indentation depth. The thing is, none of those other examples cause indentation depth problems in other languages because they don't force you through type system hoops to get useful work done. Besides, you can (ab)use Enumerator for all sorts of monadic things if needs be and end up with something quite terse. A random number generator is trivial, for instance. I'm not saying that `do` notation isn't a neat trick, it just tends to be a trick other languages don't need. Its generality is both a blessing and a curse.
- Tainnor 3y ago> The thing is, none of those other examples cause indentation depth problems in other languages They do, I've seen it happen before. Callback hell was a thing in JavaScript, before Promises happened (and later async/await). And if you've ever written in a functional programming style in a language that doesn't have a first class abstraction for monadic code, then you might have seen cascades of flatMap and map. FWIW, do notation is not the only option, Scala has for comprehensions that accomplish the same goal.
- twic 3y ago"Haskell is best at solving problems that Haskell invented and other languages do not have." -- Jon Harrop
- paldepind2 3y agoYou're absolutely right. That is particular example is bad because you don't actually need the power of flapMap/bind. But, if the available containers depended on the flavor and the available toppings depended on the flavor and/or container, then you would need flapMap/bind and do-notation would pull its weight.