Is `data PoE a = Empty | Pair a a` a monad?

后端 未结 3 1488
情话喂你
情话喂你 2021-02-13 07:09

This question comes from this answer in example of a functor that is Applicative but not a Monad: It is claimed that the

data PoE a = Empty | Pair a a deriving (         


        
3条回答
  •  忘了有多久
    2021-02-13 07:54

    Apparently, it is not a monad. One of the monad "join" laws is

    join . join = join . fmap join
    

    Hence, according to the law above, these two outputs should be equal, but they are not.

    main :: IO ()
    main = do
      let x = Pair (Pair (Pair 1 2) Empty) (Pair Empty (Pair 7 8))
      print (join . join $ x)
      -- output: Pair 1 8
      print (join . fmap join $ x)
      -- output: Empty
    

    The problem is that

    join x      = Pair (Pair 1 2) (Pair 7 8)
    fmap join x = Pair Empty Empty
    

    Performing an additional join on those does not make them equal.

    how to find that out systematically?

    join . join has type m (m (m a)) -> m (m a), so I started with a triple-nested Pair-of-Pair-of-Pair, using numbers 1..8. That worked fine. Then, I tried to insert some Empty inside, and quickly found the counterexample above.

    This approach was possible since a m (m (m Int)) only contains a finite amount of integers inside, and we only have constructors Pair and Empty to try.

    For these checks, I find the join law easier to test than, say, associativity of >>=.

提交回复
热议问题