"Haskell Programming from First Principles"의 15 장에있는 this other question과 같은 연습 문제를 해결하려고합니다. Semigroup 인스턴스를 이미 만들었고 QuickCheck 부분을 작성하는 데 문제가 있습니다.이 데이터 유형에 대한 Semigroup 법칙을 테스트하는 방법은 무엇입니까?
반군 인스턴스 만족해야 <>
은 반군의 mappend이다
a <> (b <> c) == (a <> b) <> c
.
나는 다음과 같이 올라와있다 :
import Data.Semigroup
import Test.QuickCheck
semigroupAssoc :: (Eq m, Semigroup m) => m -> m -> m -> Bool
semigroupAssoc a b c = (a <> (b <> c)) == ((a <> b) <> c)
newtype Combine a b = Combine { unCombine :: (a -> b) }
instance Semigroup b => Semigroup (Combine a b) where
(Combine f) <> (Combine g) = Combine (\x -> (f x) <> (g x))
instance CoArbitrary (Combine a b) where
coarbitrary (Combine f) = variant 0
instance (CoArbitrary a, Arbitrary b) => Arbitrary (Combine a b) where
arbitrary = do
f <- arbitrary
return $ Combine f
type CombineAssoc a b = Combine a b -> Combine a b -> Combine a b -> Bool
main :: IO()
main = do
quickCheck (semigroupAssoc :: CombineAssoc Int Bool)
모두는 No instance for (Eq (Combine Int Bool)) arising from a use of ‘semigroupAssoc’
이 불평 quickCheck
라인을 제외하고 컴파일합니다.
임의의 두 함수가 같은지 테스트하는 방법은 없다고 생각합니다. (함수는 Combine
로 감싸졌지만) 연습용 텍스트는 그러한 것이 가능함을 나타냅니다.
내가 어떻게이 작업을 할 수 있는지에 대한 아이디어가 있습니까?
편집 :
저자는이 운동에 대한 힌트를 줄 :
힌트 :이 기능은 결국 하나의 값을 입력의 에 적용됩니다. 그러나 유형 b의 값을 생성 할 수있는 여러 함수가 있습니다. 하나의 b 값을 갖도록 여러 값을 결합하려면 어떻게해야합니까? 이건 아마 까다 롭습니다! Combine 내부의 값 유형은 함수의 값임을 기억하십시오. 이 CoArbitrary를 알아 내지 못하면 빠른 검사에 대해 걱정하지 마십시오.
@ Li-yao Xia의 답변이 가장 좋은 답변 인 것 같습니다. 하지만이 CoArbitrary 인스턴스를 사용해서는 안됩니까?
최신 버전의 [기능] (https://hackage.haskell.org/package/QuickCheck-2.9.2/docs/Test-QuickCheck-Function.html)하지만 당신은 변경해야 할 것입니다 귀하의 type -'newtype Combine '재미 ab = 결합 (fun ab); Combine = Combine '(->);을 입력하십시오. 타입 Combine_Test = 'Fun' 결합 (또는 구조를 복제하는 고유 한 타입을 만들고'Fun'으로'->'를 대체) – user2407038
이 예제에서는 람다 미적분 함수를 사용하여 함수를 줄이면 전체적으로'quickCheck'를 사용하기를 원합니다 일반적으로 평등을 증명합니다. –