Предположим, у меня есть тип записи:
data Foo = Foo {x, y, z :: Integer}
Аккуратный способ написания произвольного экземпляра использует 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}.
Но теперь сжатие (Foo 0 0 0) вернет [Foo 0 0 0], что означает, что сжатие никогда не прекратится. Так что это тоже не работает.
Похоже, что здесь должно использоваться что-то другое, кроме ‹*>, но я не вижу что.