hacatu
hacatu

Reputation: 665

Can Haskell Typeclasses be Partially Implemented?

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?

Upvotes: 1

Views: 118

Answers (1)

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.

Upvotes: 3

Related Questions