【问题标题】:Polymorphic constraint多态约束
【发布时间】: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 我想到的具体类型构造函数是来自pipesProxy,具体类是Monad。我是类代理类型的类型分类实用函数,这就是约束存在的原因。根据您的建议,我将定义一个专门用于 Proxy 类型构造函数形状的 MonadP 类,并将其用作约束。缺点是,如果用户想在类代理类型中编写多态的代理实用程序函数,他们必须重新绑定 do 表示法以改用MonadP
  • 你不能直接做,但可以模拟,就像罗马的回答一样。这是相关的 GHC 票证:hackage.haskell.org/trac/ghc/ticket/2893

标签: haskell types


【解决方案1】:

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

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-06
  • 1970-01-01
相关资源
最近更新 更多