How can I make my type an instance of Arbitrary? - haskell

I have the following data and function
data Foo = A | B deriving (Show)
foolist :: Maybe Foo -> [Foo]
foolist Nothing = [A]
foolist (Just x) = [x]
prop_foolist x = (length (foolist x)) == 1
when running quickCheck prop_foolist, ghc tells me that Foo needs to be an instance of Arbitrary.
No instance for (Arbitrary Foo) arising from a use of ‘quickCheck’
In the expression: quickCheck prop_foolist
In an equation for ‘it’: it = quickCheck prop_foolist
I tried data Foo = A | B deriving (Show, Arbitrary), but this results in
Can't make a derived instance of ‘Arbitrary Foo’:
‘Arbitrary’ is not a derivable class
Try enabling DeriveAnyClass
In the data declaration for ‘Foo’
However, I can't figure out how to enble DeriveAnyClass. I just wanted to use quickcheck with my simple function! The possible values of x is Nothing, Just A and Just B. Surely this should be possible to test?

There are two reasonable approaches:
Reuse an existing instance
If there's another instance that looks similar, you can use it. The Gen type is an instance of Functor, Applicative, and even Monad, so you can easily build generators from other ones. This is probably the most important general technique for writing Arbitrary instances. Most complex instances will be built up from one or more simpler ones.
boolToFoo :: Bool -> Foo
boolToFoo False = A
boolToFoo True = B
instance Arbitrary Foo where
arbitrary = boolToFoo <$> arbitrary
In this case, Foo can't be "shrunk" to subparts in any meaningful way, so the default trivial implementation of shrink will work fine. If it were a more interesting type, you could have used some analogue of
shrink = map boolToFoo . shrink . fooToBool
Use the pieces available in Test.QuickCheck.Arbitrary and/or Test.QuickCheck.Gen
In this case, it's pretty easy to just put together the pieces:
import Test.QuickCheck.Arbitrary
data Foo = A | B
deriving (Show,Enum,Bounded)
instance Arbitrary Foo where
arbitrary = arbitraryBoundedEnum
As mentioned, the default shrink implementation would be fine in this case. In the case of a recursive type, you'd likely want to add
{-# LANGUAGE DeriveGeneric #-}
import GHC.Generics (Generic)
and then derive Generic for your type and use
instance Arbitrary ... where
...
shrink = genericShrink
As the documentation warns, genericShrink does not respect any internal validity conditions you may wish to impose, so some care may be required in some cases.
You asked about DeriveAnyClass. If you wanted that, you'd add
{-# LANGUAGE DeriveAnyClass #-}
to the top of your file. But you don't want that. You certainly don't want it here, anyway. It only works for classes that have a full complement of defaults based on Generics, typically using the DefaultSignatures extension. In this case, there is no default arbitrary :: Generic a => Gen a line in the Arbitrary class definition, and arbitrary is mandatory. So an instance of Arbitrary produced by DeriveAnyClass will produce a runtime error as soon as QuickCheck tries to call its arbitrary method.

Related

How to declare instances of a typeclass (like Show) for all types in my own typeclass?

I have a typeclass:
class Wrapper w where
open :: w -> Map String Int
close :: Map String Int -> w
It doesn't look very useful, but I use it to strongly (not just a type synonym) distinguish between semantically different varieties of Map String Ints:
newtype FlapMap = Flap (Map String Int)
newtype SnapMap = Snap (Map String Int)
...
and still have functions that operate on any type of the class.
Is there a better way to do this distinction (maybe without the Wrapper instances boilerplate)?
I want to do this:
instance (Wrapper wrapper) => Show wrapper where
show w = show $ toList $ open w
instead of writing many boilerplate Show instances as well.
Via FlexibleInstances and UndecidableInstances, GHC leads me to a point where it thinks my instance declaration applies to everything, as it allegedly clashes with the other Show instances in my code and in GHC.Show. HaskellWiki and StackOverflow answerers and HaskellWiki convince me OverlappingInstances is not quite safe and possibly confusing. GHC doesn't even suggest it.
Why does GHC first complain about not knowing which instance of fx Show Int to pick (so why it doesn't look at the constraint I give at compile time?) and then, being told that instances may overlap, suddenly know what to do?
Can I avoid allowing OverlappingInstances with my newtypes?
You can’t do this without OverlappingInstances, which as you mention, is unpredictable. It won’t help you here, anyway, so you pretty much can’t do this at all without a wrapper type.
That’s rather unsatisfying, of course, so why is this the case? As you’ve already determined, GHC does not look at the instance context when picking an instance, only the instance head. Why? Well, consider the following code:
class Foo a where
fooToString :: a -> String
class Bar a where
barToString :: a -> String
data Something = Something
instance Foo Something where
fooToString _ = "foo something"
instance Bar Something where
barToString _ = "bar something"
instance Foo a => Show a where
show = fooToString
instance Bar a => Show a where
show = barToString
If you consider the Foo or Bar typeclasses in isolation, the above definitions make sense. Anything that implements the Foo typeclass should get a Show instance “for free”. Unfortunately, the same is true of the Bar instance, so now you have two valid instances for show Something.
Since typeclasses are always open (and indeed, Show must be open if you are able to define your own instances for it), it’s impossible to know that someone will not come along and add their own similar instance, then create an instance on your datatype, creating ambiguity. This is effectively the classic diamond problem from OO multiple inheritance in typeclass form.
The best you can get is to create a wrapper type that provides the relevant instances:
{-# LANGUAGE ExistentialQuantification #-}
data ShowableWrapper = forall w. Wrapper w => ShowableWrapper w
instance Show ShowableWrapper where
show (ShowableWrapper w) = show . toList $ open w
At that point, though, you really aren’t getting much of an advantage over just writing your own showWrapper :: Wrapper w => w -> String function.

Creating custom data types with constraints

I'm trying to create a custom data type. As an example
data Time = Second Int deriving (Show)
However, this is too limiting (we could say later need milliseconds). I would like to instead define something like this:
data Time = Second Num deriving (Show)
This doesn't compile because Num has kind * -> ghc-prim-0.4.0.0:GHC.Prim.Constraint
How do I setup Time such that Second may contain any Num?
One of the best examples of why this might not be so desirable is found here at the Wikibooks section on Classes and Types. They say:
Type constraints in data declarations are less useful than it might seem at first. Consider:
data (Num a) => Foo a = F1 a | F2 a String
Here, Foo is a type with two constructors, both taking an argument of a type a which must be in Num. However, the (Num a) => constraint is only effective for the F1 and F2 constructors, and not for other functions involving Foo. Therefore, in the following example...
fooSquared :: (Num a) => Foo a -> Foo a
fooSquared (F1 x) = F1 (x * x)
fooSquared (F2 x s) = F2 (x * x) s
... even though the constructors ensure a will be some type in Num we can't avoid duplicating the constraint in the signature of fooSquared
This suggests that a reasonable option for you is to just create Time with a generic parameter, and then later ensure that the module functions that operate on Time data always have the necessary constraint for Num.
It won't be so much of a worry that someone goes off and foolishly makes Time String or something -- if they do, then none of the provided module functions are going to be helpful for them, so it doesn't matter so much.
There are also options to look up with GADTs, the {-# LANGUAGE GeneralizedNewtypeDeriving #-} pragma, and the {-# LANGUAGE DatatypeContexts #-} pragma. But usually these start to rope in unnecessary degrees of extra complexity, especially if you're a Haskell novice like me.
There is a deprecated feature called Datatype Contexts that allows you to do that:
{-# LANGUAGE DatatypeContexts #-}
data Num a => Time a = Second a deriving (Show)
t = Second (5 :: Int)
main = print t
This executes on GHC 7.8.3 (sorry, don't have 7.10 to check), but warns you about the deprecation:
t.hs:1:14: Warning:
-XDatatypeContexts is deprecated: It was widely considered a
misfeature, and has been removed from the Haskell language.
Second 5
A non-deprecated way to do it is to use Generalized Algebraic Datatypes (GADTs) (and you'll need standalone deriving as well):
{-# LANGUAGE GADTs, StandaloneDeriving #-}
data Time a where
Second :: Num a => a -> Time a
deriving instance Show a => Show (Time a)
t = Second (5 :: Int)
main = print t
If you try to create a variable with something non-Num, you'll get a compilation error:
t = Second "a"
t.hs:12:5:
No instance for (Num [Char]) arising from a use of ‘Second’
In the expression: Second "a"
In an equation for ‘t’: t = Second "a"

How to handle functions of a multi-parameter typeclass, who not need every type of the typeclass?

I've defined a typeclass similar to an interface with a bunch of functions required for my program. Sadly, it needs multiple polymorphic types, but not every function of this multi-parameter typeclass needs every type. GHC haunts me with undeduceable types and i can't get the code running.
A reduced example:
{-# LANGUAGE MultiParamTypeClasses #-}
class Foo a b where
-- ...
bar :: a -> ()
baz :: Foo a b => a -> ()
baz = bar
GHC says
Possible fix: add a type signature that fixes these type variable(s)
How can I do this for b? Especially when I want to keep b polymorphic. Only an instance of Foo should define what this type is.
This is impossible.
The underlying problem is that a multiparameter type class depends on every type parameter. If a particular definition in the class doesn't use every type parameter, the compiler will never be able to know what instance you mean, and you'll never even be able to specify it. Consider the following example:
class Foo a b where
bar :: String -> IO a
instance Foo Int Char where
bar x = return $ read x
instance Foo Int () where
bar x = read <$> readFile x
Those two instances do entirely different things with their parameter. The only way the compiler has to select one of those instances is matching both type parameters. But there's no way to specify what the type parameter is. The class is just plain broken. There's no way to ever call the bar function, because you can never provide enough information for the compiler to resolve the class instance to use.
So why is the class definition not rejected by the compiler? Because you can sometimes make it work, with the FunctionalDependencies extension.
If a class has multiple parameters, but they're related, that information can sometimes be added to the definition of the class in a way that allows a class member to not use every type variable in the class's definition.
class Foo a b | a -> b where
bar :: String -> IO a
With that definition (which requires the FunctionalDependencies extension), you are telling the compiler that for any particular choice of a, there is only one valid choice of b. Attempting to even define both of the above instances would be a compile error.
Given that, the compiler knows that it can select the instance of Foo to use based only on the type a. In that case, bar can be called.
Splitting it in smaller typeclasses might be sufficient.
{-# LANGUAGE MultiParamTypeClasses #-}
class Fo a => Foo a b where
-- ...
foo :: a -> b -> ()
class Fo a where
bar :: a -> ()
baz :: Foo a b => a -> ()
baz = bar
Assuming you really want to use more than one instance for a given a (and so cannot use functional dependencies as others mentioned), one possibility which may or may not be right for you is to use a newtype tagged with a "phantom" type used only to guide type selection. This compiles:
{-# LANGUAGE MultiParamTypeClasses #-}
newtype Tagged t a = Tagged { unTagged :: a } -- Also defined in the tagged package
-- on Hackage
class Foo a b where
bar :: Tagged b a -> ()
baz :: Foo a b => Tagged b a -> ()
baz = bar
Then you will be able to wrap your values in such a way that you can give an explicit type annotation to select the right instance.
Another way of refactoring multi-parameter type classes when they get awkward is to use the TypeFamilies extension. Like FunctionalDependencies, this works well when you can reframe your class as having only a single parameter (or at least, fewer parameter), with the other types that are different from instance to instance being computed from the actual class parameters.
Generally I've found whenever I thought I needed a multi-parameter type class, the parameters almost always varied together rather than varying independently. In this situation it's much easier to pick one as "primary" and use some system for determining the others from it. Functional dependencies can do this as well as type families, but many find type families a lot easier to understand.
Here's an example:
{-# LANGUAGE TypeFamilies, FlexibleInstances #-}
class Glue a where
type Glued a
glue :: a -> a -> Glued a
instance Glue Char where
type Glued Char = String
glue x y = [x, y]
instance Glue String where
type Glued String = String
glue x y = x ++ y
glueBothWays :: Glue a => a -> a -> (Glued a, Glued a)
glueBothWays x y = (glue x y, glue y x)
The above declares a class Glue of types that can be glued together with the glue operation, and that have a corresponding type which is the result of the "gluing".
I then declared a couple of instances; Glued Char is String, Glued String is also just String.
Finally I wrote a function to show how you use Glued when you're being polymorphic over the instance of Glue you're using; basically you "call" Glued as a function in your type signatures; this means glueBothWays doesn't "know" what type Glued a is, but it knows how it corresponds to a. You can even use Glued Char as a type, if you know you're gluing Chars but don't want to hard-code the assumption that Glued Char = String.

Using the Additive Class from the Numeric Prelude leads to Overlapping Instances

While trying to define some mathematical objects using the Numeric prelude I've run into a problem. The Additive typeclass defines an instance
instance Additive.C v => Additive.C [v]
Which I read "if v is Additive, [v] is too" (apparently I was wrong here). It's implemented something like
(+) x y = map (\(a,b) -> a + b) $ zip x y
So that [1,2,3] + [4,5,6] = [5,7,9] which is useless for what I want to do. I assumed I wouldn't have a problem as my v type isn't Additive. Unfortunately I still got an overlapping instances error which I found very confusing. I've did a little reading and I now understand that for some reason, Haskell ignores everything before the "=>" bit so I should have read the default instance as "any list is potentially additive in the sense of the default instance". I've tried using OverlappingInstances despite the fact that this extension has the reputation of being "dangerous", but even that doesn't seem to help.
Here is my testcase.
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE MultiParamTypeClasses,FlexibleInstances #-}
{-# LANGUAGE OverlappingInstances #-} --This doesn't seem to help
import NumericPrelude
import qualified Algebra.Additive as Additive
data Test = Red | Green | Blue deriving Show
instance Additive.C [Test] where
zero = undefined
(+) = undefined
negate = undefined
test = [Red] + [Green] + [Blue]
Produces the error (Update: this appears to only happen in older versions of GHC. version 7.2.2 seems to accept it):
Overlapping instances for Additive.C [Test]
arising from a use of `+'
Matching instances:
instance Additive.C v => Additive.C [v]
-- Defined in Algebra.Additive
instance [overlap ok] Additive.C [Test]
-- Defined at Testcase.hs:10:10-26
In the first argument of `(+)', namely `[Red] + [Green]'
In the expression: [Red] + [Green] + [Blue]
In an equation for `test': test = [Red] + [Green] + [Blue]
Does this mean I can't use lists because I don't want to default instance of Additive? What I really want to do is tell ghc to just forget that default instance, it that possible? If not, I'm not sure where to go from here other than dropping lists.
Edit: As #kosmikus mentioned, your example works well for me, too. I am using ghc 7.4.1.
You cannot make the compiler forget the instance as it is imported as soon as you import the module, the instance is defined in. Note that OverlappingInstances does not tell the compiler to forget an instance but to take the most specify instance that is available.
In order to prevent overlapping instances you can use a type wrapper that is used to distinguish arbitrary lists from the lists you are using. For example, you can define
data TestList = TestList [Test]
Then, you can define a custom instance of the type class for TestList. In most cases, people use record syntax to define an accessor for the list as you have to wrap and unwrap the lists.
data TestList = TestList { list :: [Test] }
In order to reduce the cost of the additional constructor you can use a newtype instead of a data.
newtype TestList = TestList { list :: [Test] }
A newtype may only have a single argument and the compiler basically handles it as if it wasn't there but uses the type information, which the constructor provides, to distinguish your lists from arbitrary lists when choosing the correct instance.

Is a scoped type statement possible?

Is it possible to do the following:
foo = bar
where
type A = (Some, Huge, Type, Sig)
meh :: A -> (A, A) -> A
I only need to use this custom type inside the where clause, so it does not make sense to define it globally.
This isn't possible. Why not just define it above the function? You don't have to export it from the module (just use an explicit export list).
By the way, if you really do have a type that big, it's probably a sign that you should factor it into smaller parts, especially if you have a lot of tuples as your example suggests; data-types would be more appropriate.
Actually, there's one, slightly ridiculous, way to approximate this:
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ScopedTypeVariables #-}
foo :: forall abbrv. (abbrv ~ (Some, Huge, Type, Sig))
=> abbrv -> abbrv
foo x = meh x (x, x)
where meh :: abbrv -> (abbrv, abbrv) -> abbrv
meh x y = {- ... -}
I can't really recommend enabling two language extensions just for the sake of abbreviating types in signatures, though if you're already using them (or GADTs instead of type families) I suppose it doesn't really hurt anything.
Silliness aside, you should consider refactoring your types in cases like this, as ehird suggests.

Resources