Hacker News new | ask | show | jobs
by mrkgnao 3247 days ago
The unpleasantness arises when writing Monad instances that don't follow the laws. Setting your disingenuity aside, try using

  xs >>= f = concat (reverse (map f xs))
or

  Array.prototype.chain = function (f) {
    return reverse(this.reduce((acc, it) => acc.concat(f(it)), []))
  }

(I don't know how JS works, but you get it) instead of

    xs >>= f = concat (map f xs)
and enjoy refactoring your code, blissfully and consciously ignorant of the laws that make a monad a monad. The laws aren't just supposed to enrich the "life of the mind".
1 comments

So, what problems will I experience while refactoring this code (if I ever wrote it)?
It won't satisfy the properties you've come to expect from the implementations you know for lists, optionals (Maybe), and so on.

Suppose you're going over some code, where you have something of the form

   xs >>= someFunction
(where xs is a list) and you change someFunction to "return":

   xs >>= return
Then you'd expect, from experience, that you can rewrite this to just

   xs
(which you can check works with all the monads you know about) but that doesn't hold for this wonky definition of the Monad instance for lists. Indeed, note that return for lists has the definition

   return x = [x]
so, with our bad >>=,

   [1, 2, 3] >>= return
   = concat (reverse (map (\x -> [x]) [1, 2, 3]))
   = concat (reverse ([[1], [2], [3]]))
   = concat [[3], [2], [1]]
   = [3, 2, 1]
which is not the same as [1, 2, 3].

https://wiki.haskell.org/Monad_laws