【发布时间】:2012-10-03 23:23:55
【问题描述】:
我有一些人为的类型:
{-# 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 都有效。
所以我的问题是,是否有办法说约束在其某些类型变量上是多态的。
【问题讨论】:
-
我认为像
class C t where toInt :: t a -> Int这样的东西不会起作用,你需要C来对* -> Constraint友善吗?善良的多态在这里会有帮助吗? -
@C.A.McCann 我想到的具体类型构造函数是来自
pipes的Proxy,具体类是Monad。我是类代理类型的类型分类实用函数,这就是约束存在的原因。根据您的建议,我将定义一个专门用于Proxy类型构造函数形状的MonadP类,并将其用作约束。缺点是,如果用户想在类代理类型中编写多态的代理实用程序函数,他们必须重新绑定 do 表示法以改用MonadP。 -
你不能直接做,但可以模拟,就像罗马的回答一样。这是相关的 GHC 票证:hackage.haskell.org/trac/ghc/ticket/2893