Я пытаюсь использовать HSpec и QuickCheck для проверки свойств моноидов (ассоциативность и элемент идентификации). Я собираюсь проверить конкретные экземпляры, но хотел бы сохранить большую часть кода полиморфным. Это то, что я придумал после нескольких часов:Используйте HSpec и QuickCheck для проверки Data.Monoid properties
module Test where
import Test.Hspec
import Test.QuickCheck
import Data.Monoid
instance (Arbitrary a) => Arbitrary (Sum a) where
arbitrary = fmap Sum arbitrary
instance (Arbitrary a) => Arbitrary (Product a) where
arbitrary = fmap Product arbitrary
prop_Monoid_mappend_mempty_x x = mappend mempty x === x
sumMonoidSpec = it "mappend mempty x = x" $ property (prop_Monoid_mappend_mempty_x :: Sum Int -> Property)
productMonoidSpec = it "mappend mempty x = x" $ property (prop_Monoid_mappend_mempty_x :: Product Double -> Property)
main :: IO()
main = hspec $ do
describe "Data.Monoid.Sum" $ do
sumMonoidSpec
describe "Data.Monoid.Product" $ do
productMonoidSpec
То, что я хотел бы иметь хотя полиморфный
monoidSpec = it "mappend mempty x = x" $ property prop_Monoid_mappend_mempty_x
и указать фактический моноидный экземпляр (сумму, произведение) и тип (Int , Double) позже. Проблема в том, что он не будет вводить проверку. Я постоянно получаю
src/[email protected]:42-18:50 No instance for (Arbitrary a0) arising from a use of property
The type variable a0 is ambiguous
Note: there are several potential instances:
instance Arbitrary a => Arbitrary (Product a)
-- Defined at /home/app/isolation-runner-work/projects/68426/session.207/src/src/Test.hs:10:10
instance Arbitrary a => Arbitrary (Sum a)
-- Defined at /home/app/isolation-runner-work/projects/68426/session.207/src/src/Test.hs:7:10
instance Arbitrary() -- Defined in Test.QuickCheck.Arbitrary
...plus 27 others …
src/[email protected]:51-18:79 No instance for (Monoid a0)
arising from a use of prop_Monoid_mappend_mempty_x
The type variable a0 is ambiguous
Note: there are several potential instances:
instance Monoid() -- Defined in Data.Monoid
instance (Monoid a, Monoid b) => Monoid (a, b)
-- Defined in Data.Monoid
instance (Monoid a, Monoid b, Monoid c) => Monoid (a, b, c)
-- Defined in Data.Monoid
...plus 18 others …
Я знаю, что нужно тягот моноидными в полиморфной версии быть Произвольное, Eq и Show, но я не знаю, как.
Вопрос в том, как выразить спецификации для моноида полиморфным способом и избежать дублирования кода?
Возможно, вас заинтересует использование [hspec-законов] (https://github.com/hspec/hspec-laws#readme) или [hspec-checkers] (http://hackage.haskell.org/package/ hspec-checkers). –