Функции отображения, используемые в свойствах 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 для своих функций do-nothing для функций...

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

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

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

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

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

Ответ 1

Вы правы 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)

Ответ 2

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