При написании некоторых экземпляров 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 = []
f
при передаче или каррировал приложение shrinkX f
при применении его к a
, b
иc