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

后端 未结 2 490
Happy的楠姐
Happy的楠姐 2021-01-05 23:41

I have defined the following data type:

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

Now I want to write that it is an instance of

相关标签:
2条回答
  • 2021-01-06 00:32

    Sadly, you can't do that—Functor instances must accept any kind of mapping function without restriction.

    You can kind of fake it, though.

    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 of the functions that would be mapped over Probability have been "deferred" by PF. We run them all at once by "lowering" back into Probability when possible

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

    And in order to convert a Probability into a fmappable PF we must "lift" it

    liftPF :: Probability a -> PF a
    liftPF p = PF $ \mp -> PD (collect $ map (first mp) (mass p))
    
    0 讨论(0)
  • 2021-01-06 00:42

    What you're writing is not a Functor. A Functor's fmap must support arbitrary value types being mapped, not just those that satisfy a certain constraint. You can make it an instance of a more general concept though. For example, the package constrained-categories defines a class of constrained functors.

    0 讨论(0)
提交回复
热议问题