我有一些做作的类型:
{-# LANGUAGE DeriveFunctor #-}
data T a = T a deriving (Functor)
...而且那种类型是一些人为的类的实例:
class C t where
toInt :: t -> Int
instance C (T a) where
toInt _ = 0
如何在函数约束中表达T a
是所有a
的某个类的实例?
例如,请考虑以下函数:
f t = toInt $ fmap Left t
直观地说,我希望上述功能能够正常工作,因为toInt
适用于所有T a
a
,但我无法在类型中表达。这不起作用:
f :: (Functor t, C (t a)) => t a -> Int
...因为当我们应用fmap
时,类型已成为Either a b
。我无法解决这个问题:
f :: (Functor t, C (t (Either a b))) => t a -> Int
...因为b
不代表普遍量化的变量。我也不能说:
f :: (Functor t, C (t x)) => t a -> Int
...或使用forall x
建议约束对所有x
有效。
所以我的问题是,是否有办法说约束对某些类型变量具有多态性。
答案 0 :(得分:7)
使用constraints包:
{-# LANGUAGE FlexibleContexts, ConstraintKinds, DeriveFunctor, TypeOperators #-}
import Data.Constraint
import Data.Constraint.Forall
data T a = T a deriving (Functor)
class C t where
toInt :: t -> Int
instance C (T a) where
toInt _ = 0
f :: ForallF C T => T a -> Int
f t = (toInt $ fmap Left t) \\ (instF :: ForallF C T :- C (T (Either a b)))