The weirdest Monad
I was going through base's haddock, when I saw that a functions has a Monad instance.
If we define have a look at Collatz conjecture, given a number n, then next number is:
3 * n + 1ifnis oddn/2ifnis even
We can define each branch as the following functions:
onEven x = x `div` 2
onOdd x = 3 * x + 1
If we want to pipe them, the following two functions are equivalent:
startOdd0 = onEven . onOdd
startOdd1 = onEven <$> onOdd
The first one uses regular Haskell composition, the second one relies Functor.
We can also try the following implementations based on Applicative and Monad:
startOdd2 = const onEven <*> onOdd
startOdd3 = const . onEven =<< onOdd
I have used const, but regarding function, I could have used pure.
This is why Reader is often defined as newtype Reader r a = Reader { runReader :: r -> a }.
As such, we can use the do-notation as follows:
startOdd4 = do
newEven <- onOdd
const $ onEven newEven
Alternatively, MOnad.Monoid is providing Endo, which defines the Monoid instance, and allows the composition as follows:
startOdd5 = appEndo $ Endo onEven <> Endo onOdd
Lastly, Control.Arrow provides ArrowChoice, which helps to combine functions, conditionally calling one or the other, which helps to build a branchless version of the Collatz as follows:
collatz x = transform $ maybeToRight x $ mfilter even $ Just x
where
transform = onOdd ||| onEven