我正在为this course homework的一个练习编写测试。
在这个作业中定义了以下数据类型:
data JoinList m a = Empty
| Single m a
| Append m (JoinList m a) (JoinList m a)
deriving (Eq, Show)
为了执行测试,我想使用JointList
生成随机QuickCheck
元素,m
是一个Monoid
,其中包含有关列表中的元素数量。这是,我想将arbitrary
定义如下:
instance (Sized m0, Monoid m0, Arbitrary a0) =>
(Arbitrary (JoinList m0 a0)) where
arbitrary = oneof [ return Empty
, liftM (Single (Size 1)) arbitrary
, liftM2 (doAppend) arbitrary arbitrary
]
where doAppend jxs jys = Append (tag jxs <> tag jys) jxs jys
其中<>
被定义为两个操作数的大小之和,Sized
类定义如下:
newtype Size = Size Int
deriving (Eq, Ord, Show, Num)
class Sized a where
size :: a -> Size
但是,这会导致以下编译器错误:
Couldn't match expected type ‘m0’ with actual type ‘Size’
‘m0’ is a rigid type variable bound by
the instance declaration at test/Spec.hs:35:10
Relevant bindings include
arbitrary :: Gen (JoinList m0 a0) (bound at test/Spec.hs:36:3)
In the first argument of ‘Single’, namely ‘(Size 1)’
In the first argument of ‘liftM’, namely ‘(Single (Size 1))’
有没有办法实现这个目标?
答案 0 :(得分:2)
我怀疑,不是支持生成由用户选择的Sized
实例注释的随机列表,而是真的只是为了支持生成由特定类型Size
注释的随机列表。您可以通过这种方式修改Arbitrary
实例声明:
instance (m ~ Size, Arbitrary a) => Arbitrary (JoinList m a) where
-- as before
您需要为Monoid
声明明显的Size
实例:
instance Monoid Size where
mempty = 0
mappend = (+)
您可以完全跳过声明Sized
课程。
或者,如果您确实打算生成由用户选择的实例注释的随机列表,那么您需要Sized
类来提供生成注释的方法,而不是消耗它们正如班级目前提供的那样。因此,例如:
class Sized a where size :: Int -> a
instance Sized Size where size = Size
然后Arbitrary
实例声明将保持不变,但会在Size
的制作中将size
替换为Single
。