3
votes

I want to create an Arbitrary instance for the following newtype, in order to use it for QuickCheck:

newtype Wrapmaybe a = Wrapmaybe {getMaybe :: Maybe a} deriving (Eq, Show)

I know that the Arbitrary instance for Maybe can be written as follows:

instance Arbitrary a => Arbitrary (Maybe a) where
     arbitrary = frequency [(1, return Nothing), (1, liftM Just arbitrary)]

How do I write the Arbitrary instance for something like the following without getting a type error or kind error:

instance Arbitrary a => Arbitrary (Wrapmaybe Maybe a) where
   etc...
1
To write such an instance, you must change the definition of Wrapmaybe - perhaps you are looking for newtype Wrap f a = Wrap (f a)user2407038

1 Answers

10
votes

Well, you could just replace each Maybe constructor in that instance with the corresponding constructor for your newtype:

instance Arbitrary a => Arbitrary (WrapMaybe a) where
  arbitrary = frequency [ (1, return $ WrapMaybe Nothing)
                        , (1, fmap (WrapMaybe . Just) arbitrary) ]

However, it's simpler to just do this once for the result, using the already existing Maybe instance:

instance Arbitrary a => Arbitrary (WrapMaybe a) where
  arbitrary = fmap WrapMaybe arbitrary

You can also write WrapMaybe <$> arbitrary. But please do not use liftM, that is obsolete! (These are all equivalent.)