I'm trying to make this data type an instance of Functor
:
data Fraction = Frac Integer Integer deriving Show
But, defining it like this will not work:
instance Functor Fraction where
pure = Frac 1 1
fmap f (Frac a b) = Frac (f a) (f b)
I want this functionality, and I would prefer the data to be an instance of Functor. But, does that violate some laws since the parameters of Fraction
are always two Integers
?
I could always just write fmap
on it's own and avoid the Functor
declaration, but I'm trying to get more familiar with the language, so any help would be appreciated!
Yes, you cannot define a functor without having a type variable to "leave out" for the declaration (Or more formally: a functor instance must be defined for something of kind * -> *
). The signature of fmap
is fmap :: (a -> b) -> f a -> f b
, so in order to satisfy that contract, it must be possible to pick any types a
and b
for the function.
You can of course just redefine Fraction
to be this:
data Fraction a = Frac a a deriving Show
... or you could use the existing data type for fractions/rational numbers in Data.Ratio, which doesn't form a functor because nobody has deemed it useful to have such an instance (what would you use it for, anyways?), but at least you'd be using a well-established and existing data structure then.