在编写一些Arbitrary
实例时,我使用以下非常机械的模式实现了几个函数:
type A = Arbitrary -- to cut down on the size of the annotations below
shrink1 :: (A a ) => (a -> r) -> (a -> [r])
shrink2 :: (A a, A b ) => (a -> b -> r) -> (a -> b -> [r])
shrink3 :: (A a, A b, A c) => (a -> b -> c -> r) -> (a -> b -> c -> [r])
shrink1 f a = [f a' | a' <- shrink a]
shrink2 f a b = [f a' b | a' <- shrink a] ++ [f a b' | b' <- shrink b]
shrink3 f a b c = [f a' b c | a' <- shrink a] ++ [f a b' c | b' <- shrink b] ++ [f a b c' | c' <- shrink c]
我手动将这些函数写到 ,shrink7
这似乎足以满足我的需要。但我不禁想知道:这可以合理地自动化吗?解决方案的奖励积分:
- 允许
shrink0 f = []
- 生成所有的收缩器
- 有很多类型类黑客,我喜欢
- 跳过可怕的扩展,如不连贯/不可判定/重叠的实例
- 让我也吃蛋糕:不需要我在传递它时 uncurry或在应用它时
f
curry 应用程序,和shrinkX f
a
b
c