假设我有一个记录类型:
data Foo = Foo {x, y, z :: Integer}
编写 Arbitrary 实例的一种简洁方式使用 Control.Applicative,如下所示:
instance Arbitrary Foo where
arbitrary = Foo <$> arbitrary <*> arbitrary <*> arbitrary
shrink f = Foo <$> shrink (x f) <*> shrink (y f) <*> shrink (z f)
因此, Foo 的收缩列表是其成员的所有收缩的笛卡尔积。
但是,如果其中一个收缩返回 [ ] 那么整个 Foo 将不会收缩。所以这行不通。
我可以尝试通过在收缩列表中包含原始值来保存它:
shrink f = Foo <$> ((x f) : shrink (x f)) <*> ... {and so on}.
但是现在shrink (Foo 0 0 0) 将返回[Foo 0 0 0],这意味着收缩永远不会终止。所以这也行不通。
看起来这里应该使用除了 <*> 以外的其他东西,但我看不到是什么。