I want to make a pair type to represent modular arithmetic. I made its constructor
{- LANGUAGE GADTs -}
data Zn e where
Zn :: Integer -> Integer -> Zn Integer
because I would like to be able to fmap
over it and all the things.
So if I try to make it a Functor
instance
instance Functor Zn where
fmap f (Zn s n) = Zn s $ mod (f n) s
I get Could not deduce: b ~ Integer from the context: a ~ Integer
. Of course it cannot deduce this because this data type does not have a meaningful notion of fmap :: (a -> b) -> Zn a -> Zn b
for all a
and b
, but it does whenever a
and b
are such that one could actually construct Zn
instances from them (ie Integer
). I also tried having the Zn
constructor and all methods require Integral e
but I get a similar problem. In that case, s
has type a
so constructing a Zn
with it and f n :: b
fails. In the second case I could convert s
from a
to Integer
and then to b
but this is clunky. The whole thing is a bit clunky. I'm just doing it because I want to be able to implement Functor
and Applicative
to perform mod
after mapping a function so I can just implement +
as liftA2 (+)
and so on. The modulus s
should be part of the type but dependent types are not practical in Haskell as far as I know.
Is it possible to have a type with kind * -> *
implement Functor
only for some arguments?
You're looking for MonoFunctor
. It's just like Functor
, but works with a fixed inner type instead of being parametrically polymorphic. Here's how you'd implement it for your type:
{-# LANGUAGE TypeFamilies #-}
import Data.MonoTraversable
data Zn = Zn Integer Integer
type instance Element Zn = Integer
instance MonoFunctor Zn where
omap f (Zn s n) = Zn s $ mod (f n) s
However, be warned that such an instance isn't exactly lawful. You may be better off just making a modMap
function or something, to avoid people making bad assumptions about how it will work.