7

我有一些人为的类型:

{-# 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 aall 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

所以我的问题是,是否有办法说约束在其某些类型变量上是多态的。

4

1 回答 1

7

使用约束包:

{-# 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)))
于 2012-10-04T00:06:35.853 回答