首页 > 解决方案 > Haskell quickBatch 测试:Applicative Monoid ZipList

问题描述

我正在尝试对ZipList Monoid haskellquickBatch提供的解决方案进行测试。我需要一些关于如何从这里继续的建议,或者我应该尝试其他方法吗?我该如何为此得出解决方案?EqProp (Ap f a)

newtype Ap f a = Ap { getAp :: f a }
  deriving (Eq, Show)
instance (Applicative f, Semigroup a) =>
  Semigroup (Ap f a) where
    Ap xs <> Ap ys = 
      Ap $ liftA2 (<>) xs ys
instance (Applicative f, Monoid a) => 
  Monoid (Ap f a) where
    mempty = Ap $ pure mempty
    Ap xs `mappend` Ap ys = 
      Ap $ liftA2 mappend xs ys
app :: Ap ZipList (Sum Int)
app = Ap (ZipList [1,2 :: Sum Int])
test :: Ap ZipList (Sum Int)
test = app <> app
instance Arbitrary (f a) =>
  Arbitrary (Ap f a) where
    arbitrary = Ap <$> arbitrary  
instance Eq a => EqProp (Ap f a) where
  xs =-= ys = xs' `eq` ys' where 
    xs' = 
      let (Ap l) = xs
        in take 3000 l
    ys' = 
      let (Ap l) = ys
        in take 3000 l
main :: IO ()
main = do
  quickBatch $ monoid app

此代码有 2 条类似的错误消息,每条有 2 行: in take 3000 l

错误信息:

Couldn't match type ‘f’ with ‘[]’
‘f’ is a rigid type variable bound by
the instance declaration at Line of Code
Expected type: [a]
Actual type: f a
In the second argument of ‘take’, namely ‘l’
In the expression: take 3000 l

标签: haskell

解决方案


问题是你说

instance Eq a => EqProp (Ap f a)

但随后在您使用的实例中take,它仅适用于列表而不适用于任意类型的构造函数f。出于测试目的,仅使用以下任一限制实例是合理的

instance Eq a => EqProp (Ap ZipList a)

或者

instance (Eq a, f ~ ZipList) => EqProp (Ap f a)

你仍然需要解开ZipLists. 其中任何一个都需要额外的语言扩展;只需按照错误消息所说的去做。在测试之外,使用新类型包装器通常是更好的做法:类似于

{-# language GeneralizedNewtypeDeriving, DeriveTraversable #-}
newtype MonZipList a = MonZipList (Ap ZipList a)
  deriving (Applicative, Alternative, Semigroup
    , Monoid, Functor, Foldable, Traversable, ...)

推荐阅读