[英]Applicative instance of List runs forever in composition law test with QuickCheck/Checkers
[英]How to test the homomorphism law of an Applicative instance?
我在做Typeclassopedia的練習; 在“ Applicative
部分”中,我編寫了ZipList
的pure
函數,並檢查它是否符合Applicative
法律。
我檢查了:
但是,當我嘗試檢查“同態”定律時,我發現GHCi沒有獲得作為MZipList
的結果。
我認為這是因為我想為我的Applicative
類型類指定pure
類型。 我如何運行一個pure
功能,而不<*>
它Applicative
立刻?
這是MZipList
定義和類實例:
newtype MZipList a = MZipList { getZipList :: [a] }
deriving (Show)
instance Functor MZipList where
fmap gs x = pure gs <*> x
instance Applicative MZipList where
pure a= MZipList (repeat a)
(MZipList gs) <*> (MZipList xs) = MZipList (zipWith ($) gs xs)
例如,當我檢查“交換”法時:
*Main> (MZipList [(*2),(*3),(*4)]) <*> pure (2)
MZipList {getZipList = [4,6,8]}
*Main> pure ($ 2) <*> (MZipList [(*2),(*3),(*4)])
MZipList {getZipList = [4,6,8]}
但是,當我檢查“同態”定律時, MZipList
的pure
不被調用:
*Main> pure (*2) <*> pure 2
4
*Main> pure ((*2) 2)
4
*Main>
這是為什么?
pure
? pure
只是將“對象”“插入”特定Applicative
單子內部的函數。 例如在:
test :: [Int]
test = pure 1 -- [1]
我們將1
插入到monad列表中,這將導致單例[1]
。 如果您已經閱讀過Monad
類,那么pure
與return
基本相同(如果您不擔心的話)。
您的Applicative
實例似乎運行良好。
在GHCi中運行命令時,您基本上位於IO
monad中,這也是一個Applicative
。 因此,通常, pure x
返回IO (type of x)
。
在:
pure (*2) <*> pure 2
您要在IO
對象中“放入” (*2)
,然后在IO
對象中也放入2
,最后按instance Applicative IO
中的定義調用<*>
。
您沒有測試MZipList
實例。
在第二個示例中,您只是調用:
pure ((*2) 2)
如果您還記得, (*2) 2
只需將(*2)
應用於2
,從而真正執行2 * 2
。 因此,您的電話實際上是:
pure 4
在GHCi中(仍然在IO
monad的上下文中)返回IO Int
對象。
要測試“同態”定律,您只需要向編譯器提供有關您真正想要哪種類型的小提示:
所以代替:
pure (*2) <*> pure 2
你會寫:
pure (*2) <*> (pure 2 :: MZipList Int)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.