вызов класса типов :с переменными аргументами и результатами

При написании некоторых экземпляров 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
9
задан Daniel Wagner 17 August 2012 в 23:36
поделиться