Reputation: 1917
Is it good style to put the instance declarations for uncommon typeclasses in extra modules?
As an example I have this simple tree type:
module Data.Tree where
data Tree a = Leaf a
| Node (Tree a) (Tree a)
Suppose I want to use QuickCheck's Arbitrary
typeclass to generate random values of type Tree
(and be able to use them not only in tests).
What is best? To put them in the same module where Tree
is defined
module Data.Tree where
import QuickCheck.Arbitrary
data Tree a = ...
instance Arbitrary a => Arbitrary (Tree a) where
...
or to outsource the instance declaration to another module to avoid the dependency to QuickCheck.Arbitrary
in Data.Tree
module Data.Tree.Arbitrary where
import Data.Tree
import QuickCheck.Arbitrary
instance Arbitrary a => Arbitrary (Tree a) where
...
or something else entirely?
Upvotes: 1
Views: 55
Reputation: 120711
It's generally a good idea to avoid orphan instances: those are always good for surprises, and rather hard to find.
So, yes, put the instance in the module where Tree
is defined. This blows up the module a bit, but it shouldn't really be an issue. Of the total build time of the whole package it shouldn't matter much if you have one larger module or two smaller ones.
When you can completely avoid a package dependency, this might make an orphan instance worthwhile, because installing a package is obviously a much greater performance issue than importing a module from an installed package.
Upvotes: 3