Why can AccValidation not have a Monad instance?

前端 未结 2 501
野的像风
野的像风 2021-01-02 16:57

From the documentation of the validation package:

The AccValidation data type is isomorphic to Either, but has an instance of <

2条回答
  •  刺人心
    刺人心 (楼主)
    2021-01-02 17:32

    The (<*>) = ap exigence can be stated explicitly in terms of (>>=):

    u <*> v = u >>= \f -> fmap f v -- [1]
    

    Now, given the Functor and Applicative instances for AccValidation, we have:

    fmap _ (AccFailure e) = AccFailure e -- [2]
    
    AccFailure e1 <*> AccFailure e2 = AccFailure (e1 <> e2) -- [3]
    

    If we make u = AccFailure e1 and v = AccFailure e2 in [1], we get:

    AccFailure e1 <*> AccFailure e2 = AccFailure e1 >>= \f -> fmap f (AccFailure e2)
    

    Substituting [2] and [3] into that leads us to:

    AccFailure (e1 <> e2) = AccFailure e1 >>= \_ -> AccFailure e2 -- [4]
    

    The problem is that it is impossible to write a (>>=) such that [4] holds. The left-hand side depends on an e2 value which must originate, on the right-hand side, from applying \_ -> AccFailure e2 :: Semigroup e => a -> AccValidation e b. However, there is nothing to which it can be applied -- in particular, e1 has the wrong type. (See the final two paragraphs of Cactus' answer for further discussion of this point.) Therefore, there is no way of giving AccValidation a Monad instance which is consistent with its Applicative one.

提交回复
热议问题