如何测试应用实例的同态定律?

时间:2014-10-22 07:38:45

标签: haskell typeclass proof applicative homomorphism

我正在进行Typeclassopedia的练习;在Applicative部分,我编写了ZipList pure函数,并检查它是否符合Applicative定律。

我已经查过:

  • 身份法
  • 交换法
  • 组成法

但是当我试图检查"同态"法律,我发现GHCi没有得到MZipList的结果。

我认为这是因为我错过了将pure指定为Applicative类型的类。如何在没有pure <*>的情况下立即运行Applicative函数?{/ p>

这里是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)

当我查看&#34; Interchange&#34;法律,例如:

*Main> (MZipList [(*2),(*3),(*4)]) <*> pure (2)
MZipList {getZipList = [4,6,8]}
*Main> pure ($ 2) <*> (MZipList [(*2),(*3),(*4)])
MZipList {getZipList = [4,6,8]}

但是当我检查&#34; Homomorphism&#34;法律,MZipList&#39; s pure未被调用:

*Main> pure (*2) <*> pure 2
4
*Main>  pure ((*2) 2)
4
*Main>

为什么?

1 个答案:

答案 0 :(得分:6)

什么是pure

pure只是一个在特定Applicative monad中“插入”对象的函数。例如:

test :: [Int]
test = pure 1 -- [1]

我们将1插入到列表monad中,从而产生单[1]。如果您已阅读Monad课程,则purereturn基本相同(如果您不必担心)。

Applicative的实例似乎工作正常。

您的测试

在GHCi中运行命令时,您基本上位于IO monad中,它也是Applicative。因此,一般情况下,pure x会返回IO (type of x)

在:

pure (*2) <*> pure 2

您将(*2)“放”在IO对象中,然后将2放入IO对象中,最后按定义调用<*>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)

Live demo