[英]How to add a class constraint to a Functor instance declaration in Haskell?
我已经定义了以下数据类型:
data Probability a = PD { mass :: [(a, Ratio Int)] }
现在我想写一下它是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))
但是,我收到以下错误:
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)
遗憾的是,你无法做到这一点 - Functor
实例必须接受任何类型的映射功能而不受限制。
不过,你可以假装它。
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
运行它们
lowerPF :: Eq a => PF a -> Probability a
lowerPF pf = unPF pf id
为了将Probability
转换为可fmappable
PF
我们必须“提升”它
liftPF :: Probability a -> PF a
liftPF p = PF $ \mp -> PD (collect $ map (first mp) (mass p))
你写的不是Functor
。 Functor
的fmap
必须支持被映射的任意值类型,而不仅仅是那些满足某个约束的值。 您可以将其作为更一般概念的实例。 例如,包约束类别定义了一类约束仿函数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.