I am working through the Haskell Book and have come to the point of writing an Arbitrary instance for newType Comp
. The code is below
instance Show (Comp a) where
show f = "Unicorns!!"
newtype Comp a =
Comp { unComp :: (a -> a) }
instance (Semigroup a) => S.Semigroup (Comp a) where
(Comp fx) <> (Comp fy) = Comp (fx . fy)
instance (CoArbitrary a, Arbitrary a) => Arbitrary (Comp a) where
arbitrary = do
f <- Test.QuickCheck.arbitrary
return (Comp f)
type CompAssoc = String -> Comp String -> Comp String -> Comp String -> Bool
compAssoc :: (S.Semigroup a, Eq a) => a -> Comp a -> Comp a -> Comp a -> Bool
compAssoc v a b c = (unComp (a <> (b <> c)) $ v) == (unComp ((a <> b) <> c) $ v)
and tested with
main :: IO ()
main = do
quickCheck (compAssoc :: CompAssoc)
My question revolves around the Arbitrary instance. It is generating a function to be passed to return (Comp f)
. I understand (though not fully why) that this has to be scoped to CoArbitrary. But if that thing passed to return (Comp f)
is CoArbitrary
, how can it also be Arbitrary
? I guess it seems to be like these constraints both refer to the pass/return type of the function and the function itself. I'm a little confused.
a
was a type like inComp String
, as is used inCompAssoc
, but thea
here represents the function that you pass when constructing aComp
. You only use the concrete types when declaring functions. I guess I mixed up type constructors and data constructors. – DihedronCompp
and it still requires the type constructor for the Arbitrary declaration. but the Type Constructor takes a type likeString
or whatever has a Semigroup instance. But here we are trying to generate functions, i.e. the thing passed to the data constructor. How can we limitComp a
(the data constructor to needCoArbitrary
when it expects something likeString
which is something that has a Semigroup instance? – Dihedrona
going toComp
, that is restraining the arg and return type of theunComp
function, saying that I must be able to generate a function that takes atype a
– DihedronCoArbitrary a
as a restraint, but justArbitrary a
, then I can return a randoma
value. But when I addCoArbitrary a
, the random value that is returned is a function that can accept ana
. That is,CoArbitrary
speaks about returning a function that accepts values of a certain type. – Dihedron