我发现这个 Applicative 实例至少有 2 个 pure 实现,它们遵循所有的规律(身份、同态、交换、组合)。其中之一仍然是错误的吗?

data List a =
    Nil
  | Cons a (List a)
  deriving (Eq, Show)

newtype ZipList' a =
  ZipList' (List a)
  deriving (Eq, Show)

instance Applicative ZipList' where
  ZipList' fss <*> ZipList' xss = ZipList' $ applicate fss xss
    where applicate (Cons f fs) (Cons x xs) = Cons (f x) (applicate fs xs)
          applicate Nil         _           = Nil
          applicate _           Nil         = Nil
pure x = ZipList' (Cons x Nil)

或者
pure a = ZipList' as
  where as = Cons a as

最佳答案

对于第一个 pure ,恒等律不成立。事实上,这条法律是这样说的:

pure id <*> v = v

因此,这意味着:
ZipList' (Cons id Nil) <*> v = v

对于所有 v 。但这并不成立。说 v = ZipList' (Cons 1 (Cons 2 Nil)) ,所以基本上是一个列表 [1,2] 。那么人们期望:
ZipList' (Cons id Nil) <*> ZipList' (Cons 1 (Cons 2 Nil)) = ZipList' (Cons 1 (Cons 2 Nil))

但是,如果我们评估您的 Applicative 实现,我们会看到:
ZipList' (Cons id Nil) <*> ZipList' (Cons 1 (Cons 2 Nil))
    = ZipList' (applicate (Cons id Nil) (Cons 1 (Cons 2 Nil)))
    = ZipList' (Cons (id 1) (applicate Nil (Cons 2 Nil)))
    = ZipList' (Cons 1 Nil)

但这不是我们对恒等律所期望的,因为在这里我们获得了一个基本上是 ZipList'[1] ,而它应该是 [1,2]

关于haskell - 如何为 Applicative 实例制作合适的 "pure"?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59956838/

10-13 07:02