haskell - Haskell quickBatch 测试:Ap ZipList 的新类型包装器
问题描述
我正在尝试根据Haskell quickBatch testing: Applicative Monoid ZipListAp ZipList
中给出的建议为我做一个包装新类型。我的 GHC 版本是 8.8.4,我使用堆栈进行编译。我的完整代码:
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 ZipList a) where
xs =-= ys = xs' `eq` ys' where
xs' =
let (Ap (ZipList l)) = xs
in take 3000 l
ys' =
let l = (getZipList . getAp) ys
in take 3000 l
newtype MonZipList a =
MonZipList (Ap ZipList a)
deriving (Semigroup, Monoid, Eq, Show)
deriving instance Functor f =>
Functor (Ap f)
deriving instance Applicative f =>
Applicative (Ap f)
monapp :: MonZipList (Sum Int)
monapp = MonZipList app
instance Arbitrary a =>
Arbitrary (MonZipList a) where
arbitrary = MonZipList <$> arbitrary
instance Eq a => EqProp (MonZipList a) where
(=-=) = eq
main :: IO ()
main = do
quickBatch $ monoid app
quickBatch $ monoid monapp
quickBatch $ functor monapp
quickBatch $ applicative monapp
基本quickBatch $ monoid app
测试运行良好,没有问题。
我面临的问题是,当我运行时quickBatch $ monoid monapp
,monoid 测试挂在 mconcat 测试中并且无法停止。我不得不关闭我的 WSL Bash 以阻止它运行。
当我尝试quickBatch $ functor monapp
orquickBatch $ applicative monapp
时,抛出错误,从而使包装器 newtype 的有效性受到质疑:无法将类型 'Sum Int' 与 '(a0, b0, c0)' 预期类型匹配:MonZipList (a0, b0, c0) 实际type: MonZipList (Sum Int) 在'functor'的第一个参数中,即'monapp'</p>
这些新型包装器问题有什么解决方案吗?
解决方案
看起来您遇到了两个不同的问题,这两个问题都不是使用 newtype 包装器的结果。
首先,ZipList
在 的情况下,引擎盖下有无限的列表mempty
,这可能就是您的monoid monapp
测试挂起的原因。看起来您正在您的实例中处理这个问题EqProp (Ap ZipList a)
,但不是在您的EqProp (MonZipList a)
实例中。这有点奇怪。也许您的意思是EqProp (Ap ZipList a)
完全删除实例并只拥有EqProp (MonZipList a)
实例,但使用实例中的代码EqProp (Ap ZipList a)
?就像是:
instance Eq a => EqProp (MonZipList a) where
MonZipList (Ap (ZipList xs)) =-= MonZipList (Ap (ZipList ys)) =
take 3000 xs `eq` take 3000 ys
至于functor monapp
,类型根本没有排列。对于functor
和applicative
,您需要提供 3 种任意类型供测试使用。
您可能不知道这一点,但是您提供给的实际值functor
是无关紧要的——它只对类型感兴趣。就个人而言,我发现直接为这些函数提供类型作为参数更容易,如下所示:
{-# LANGUAGE TypeApplications #-}
main = do
quickBatch $ monoid @(MonZipList (Sum Int)) undefined
quickBatch $ functor @MonZipList @Int @Bool @Char undefined
quickBatch $ applicative @MonZipList @String @Int @Char undefined
现在很清楚发生了什么:对于functor
测试,使用函子以及来自 types 、和MonZipList
的任意(和 coarbitrary)值进行测试。如果您真的想用其他类型进行测试,您可以随意更改这些类型或运行多个测试。Int
Bool
Char
functor
推荐阅读
- reactjs - 将孩子传递给 Typescript 中的专用 React 组件
- azure - 使用 KeyVault 的 Azure 应用服务 JSON 转换
- redis - 将数据从 Redis 流移动到不在内存中的存储
- javascript - JS - 将 JSON 的嵌套数组转换为单个对象
- javascript - 纯 JavaScript 的 HTML 暗模式
- nestjs - 如何在 Nestjs 中设置默认时区?
- java - Mockito 中的模拟链调用导致 NullPointerException 或 WrongTypeOfReturnValue
- sql - 如何将重复字段聚合到单独的列中
- python - 在detectron2中,我怎么能把文字放在图像上?
- c# - 无法在 VS Code 中正确添加 .dll 引用