Elixir doesn’t even need a special syntax — it gets Haskell’s LambdaCase as a natural consequence of case being just another function, and the pipe operator always chaining by the first argument.
Haskell’s >>= is doing something slightly different. ‘getThing >>= \case…’ means roughly ‘perform the action getThing, then match the result and perform the matched branch’
Whereas ‘getThing |> \case…’ means ‘pattern match on the action getThing, and return the matched action (without performing it).
The >>= operator can also be used for anything satisfying the Monad laws, e.g. your actions can be non-deterministic.
Pedantry: >>= can be used for any instance of the Monad typeclass. GHC isn't sufficiently advanced to verify that a given Monad instance satisfies the monad laws; it can verify that the instance satisfies the type definition, but for e.g. the identity law "m >>= return === m" the instance can still return something violating the law (not something substitutable with m).
Being able to pipe into def, defp, defmodule, if, etc. is fantastic! But apparently you say at least in the case of case, it's not a macro, and it's just a function which returns a monad—I guess it's the same effect afterall? Is that why people say Haskell can get away with lack of Lisp-style macros because of its type system and laziness?
I was wrong about this. Case is a macro (a special-cased macro even, defined at https://github.com/elixir-lang/elixir/blob/4def31f8abea5fba4...), not a function. It works with pipes because in the AST it's a call, unlike in Haskell where case is its own thing.
Haskell’s >>= is doing something slightly different. ‘getThing >>= \case…’ means roughly ‘perform the action getThing, then match the result and perform the matched branch’
Whereas ‘getThing |> \case…’ means ‘pattern match on the action getThing, and return the matched action (without performing it).
The >>= operator can also be used for anything satisfying the Monad laws, e.g. your actions can be non-deterministic.