How to add a class constraint to a functor instance declaration in Haskell?

I defined the following data type:

data Probability a = PD { mass :: [(a, Ratio Int)] } 

Now I want to write that this is an instance Functor:

collect :: (Eq a, Num b) => [(a, b)] -> [(a, b)]
collect al = map collect' keys where
    keys = nub $ map fst al
    collect' k = (k, sum (map snd (matches k)))
    matches k = filter ((==) k . fst) al

instance (Eq a) => Functor (Probability a) where
    fmap f p = PD (collect $ map (first f) (mass p))

However, I get the following error:

Kind mis-match
The first argument of `Functor' should have kind `* -> *',
but `Probability a' has kind `*'
In the instance declaration for `Functor (Probability a)'

How to add a mandatory restriction Eq a? (I am using GHC 7.4.1)

+3
source share
2 answers

Unfortunately, you cannot do this. Functorinstances must accept any display function without restriction.

However, you can fake it.

newtype PF a = PF { unPF :: forall r . Eq r => (a -> r) -> Probability r }

instance Functor PF where
  fmap f (PF p) = PF (\mp -> p (mp . f))

Here, all the functions that will be displayed on top Probabilityhave been “delayed” by PF. We run them all at once, “dropping” back on Probabilitywhen possible

lowerPF :: Eq a => PF a -> Probability a
lowerPF pf = unPF pf id

a Probability fmappable PF, ""

liftPF :: Probability a -> PF a
liftPF p = PF $ \mp -> PD (collect $ map (first mp) (mass p))
+7

, , . fmap , , . . , constrained-categories .

+3

All Articles