Как сделать правильный «чистый» для аппликативного экземпляра? - PullRequest
4 голосов
/ 28 января 2020

Я обнаружил, что есть по крайней мере 2 реализации pure для этого аппликативного экземпляра, которые следуют всем l aws (идентичность, гомоморфизм, обмен, композиция). Один из них все еще не прав?

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

Ответы [ 2 ]

9 голосов
/ 28 января 2020

Для первого 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].

3 голосов
/ 30 января 2020

Каждый <*> может поддерживать не более одного действительного 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
...