maxloo
maxloo

Reputation: 491

Haskell quickBatch testing: Applicative Monoid ZipList

I'm trying to do a quickBatch test on the solution provided at ZipList Monoid haskell. I'll need some advice as to how to continue from here or should I try something else for EqProp (Ap f a)? How do I go about deriving a solution for this?

newtype Ap f a = Ap { getAp :: f a }
  deriving (Eq, Show)
instance (Applicative f, Semigroup a) =>
  Semigroup (Ap f a) where
    Ap xs <> Ap ys = 
      Ap $ liftA2 (<>) xs ys
instance (Applicative f, Monoid a) => 
  Monoid (Ap f a) where
    mempty = Ap $ pure mempty
    Ap xs `mappend` Ap ys = 
      Ap $ liftA2 mappend xs ys
app :: Ap ZipList (Sum Int)
app = Ap (ZipList [1,2 :: Sum Int])
test :: Ap ZipList (Sum Int)
test = app <> app
instance Arbitrary (f a) =>
  Arbitrary (Ap f a) where
    arbitrary = Ap <$> arbitrary  
instance Eq a => EqProp (Ap f a) where
  xs =-= ys = xs' `eq` ys' where 
    xs' = 
      let (Ap l) = xs
        in take 3000 l
    ys' = 
      let (Ap l) = ys
        in take 3000 l
main :: IO ()
main = do
  quickBatch $ monoid app

There are 2 similar error messages for this code, each for the 2 lines: in take 3000 l

Error message:

Couldn't match type ‘f’ with ‘[]’
‘f’ is a rigid type variable bound by
the instance declaration at Line of Code
Expected type: [a]
Actual type: f a
In the second argument of ‘take’, namely ‘l’
In the expression: take 3000 l

Upvotes: 0

Views: 80

Answers (1)

dfeuer
dfeuer

Reputation: 48591

The problem is that you say

instance Eq a => EqProp (Ap f a)

but then in the instance you use take, which works only for lists and not arbitrary type constructors f. For testing purposes, it would be reasonable to just limit the instance with either

instance Eq a => EqProp (Ap ZipList a)

or

instance (Eq a, f ~ ZipList) => EqProp (Ap f a)

You'll still need to unwrap the ZipLists. Either of these will require additional language extensions; just do what the error messages say. Outside of testing, it's usually better practice to use a newtype wrapper: something like

{-# language GeneralizedNewtypeDeriving, DeriveTraversable #-}
newtype MonZipList a = MonZipList (Ap ZipList a)
  deriving (Applicative, Alternative, Semigroup
    , Monoid, Functor, Foldable, Traversable, ...)

Upvotes: 2

Related Questions