如何为 Applicative 实例制作适当的 "pure"?
How to make a proper "pure" for an Applicative instance?
我发现这个 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) <*> <i>v</i> = <i>v</i>
所有 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
我发现这个 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) <*> <i>v</i> = <i>v</i>
所有 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