我已经发现,此应用实例至少有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
,identity法则不适用[[not。确实,该法律规定:
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]
。
<*>
最多可以支持一个有效的pure
。假设pure1
和pure2
都合法。然后,对于任何x
,pure2 x
= -- Identity for pure1
pure1 id <*> pure2 x
= -- Interchange for pure2
pure2 ($x) <*> pure1 id
= -- Functor/Applicative for pure2
fmap ($x) (pure1 id)
= -- Functor/Applicative for pure1
pure1 ($x) <*> pure1 id
= -- Homomorphism for pure1
pure1 x