Search code examples
haskelltypesfunctorfractions

Is it impossible to create a Functor instance of this data type?


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!


Solution

  • 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.