Отображение функций, используемых в свойствах QuickCheck

Я пытаюсь написать свойство QuickCheck, которое принимает одну или несколько функций в качестве входных данных. Для простоты рассмотрим свойство, позволяющее проверить, что состав функций эквивалентен последовательному приложению функций и тестируемому драйверу с быстрой и грязной структурой:

import Test.QuickCheck

prop_composition :: (Int -> Int) -> (Int -> Int) -> Int -> Bool
prop_composition f g x = (f . g) x == f (g x)

main :: IO ()
main = quickCheck prop_composition

К сожалению, это не компилируется, потому что входные данные для свойства должны быть реализованы Show так что QuickCheck может сообщить, какие входные данные вызвали сбой, но нет Show реализация для функций:

Test.hs:10:7:
    No instance for (Show (Int -> Int))
      arising from a use of `quickCheck' at Test.hs:10:7-33
    Possible fix: add an instance declaration for (Show (Int -> Int))
    In the expression: quickCheck prop_composition
    In the definition of `main': main = quickCheck prop_composition

Я пытался написать свой собственный бездействующий экземпляр Show для функций...

instance Show (a -> b) where
    show _ = "[func]"

... который компилируется, но выдает предупреждение с -Wall...

Test.hs:3:9: Warning: orphan instance: instance Show (a -> b)

... что заставляет меня думать, что есть более правильный способ сделать это.

Моя интуиция говорит мне, что ответ лежит в Test.QuickCheck.Function модуль, но он недокументирован, и я не могу понять, просто посмотрев на сигнатуры типов, для чего здесь что-то есть, или как он предназначен для использования.

2 ответа

Решение

Вы правы Test.QuickCheck.Function это правильный ответ. Вы просто меняете типы:

prop_composition       :: Fun Int Int -> Fun Int Int -> Int -> Bool
prop_composition f g x = ((apply f) . (apply g)) x == (apply f) ((apply g) x)

import Text.Show.Functions может также использоваться с сохранением оригинальной подписи.

Другие вопросы по тегам