いくつかの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