本文介绍了如何将类约束添加到Haskell中的Functor实例声明中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经定义了以下数据类型:

I have defined the following data type:

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

现在我想写出它是一个 Functor的实例

Now I want to write that it is an instance of 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)'

如何添加必要的 Eq a 约束? (我正在使用GHC 7.4.1)

How can I add the necessary Eq a constraint? (I'm using GHC 7.4.1)

推荐答案

可悲的是,你不能这么做 - Functor 实例必须接受任何类型的映射函数而不受限制。

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))

这里,映射到 Probability 的所有函数都被延迟由 PF 。在可能的情况下,我们通过降低回到 Probability 中来一次性运行它们。

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

为了将一个 Probability 转换为 fmappable PF ,我们必须提升它

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))

这篇关于如何将类约束添加到Haskell中的Functor实例声明中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-22 19:37
查看更多