3

好吧,我已经在 Haskell 中定义了代表单变量多项式的自己的数据类型。

data Polinomio a where
    Pol  :: (Num a) => a -> Integer -> Polinomio a -> Polinomio a
    Cons :: (Num a) => a -> Polinomio a

我在这里使用 GADT 来约束 a 变量属于 Num 类。现在我想为 Functor 类定义我自己的实例

instance Functor Polinomio where
    fmap f (Cons x) = Cons $ f x
    fmap f (Pol x g p) = Pol (f x) g (fmap f p)

它没有编译给我这个原因:

Polinomio_GADT.hs:31:23:
Could not deduce (Num b) arising from a use of `Cons'
from the context (Num a)
  bound by a pattern with constructor
             Cons :: forall a. Num a => a -> Polinomio a,
           in an equation for `fmap'
  at Polinomio_GADT.hs:31:13-18
Possible fix:
  add (Num b) to the context of
    the data constructor `Cons'
    or the type signature for
         fmap :: (a -> b) -> Polinomio a -> Polinomio b
In the expression: Cons
In the expression: Cons $ f x
In an equation for `fmap': fmap f (Cons x) = Cons $ f x

Polinomio_GADT.hs:32:26:
Could not deduce (Num b) arising from a use of `Pol'
from the context (Num a)
  bound by a pattern with constructor
             Pol :: forall a.
                    Num a =>
                    a -> Integer -> Polinomio a -> Polinomio a,
           in an equation for `fmap'
  at Polinomio_GADT.hs:32:13-21
Possible fix:
  add (Num b) to the context of
    the data constructor `Pol'
    or the type signature for
         fmap :: (a -> b) -> Polinomio a -> Polinomio b
In the expression: Pol (f x) g (fmap f p)
In an equation for `fmap':
    fmap f (Pol x g p) = Pol (f x) g (fmap f p)
In the instance declaration for `Functor Polinomio'

所以我尝试使用语言扩展 InstanceSigs 将此约束添加到 fmap 定义中:

instance Functor Polinomio where
    fmap :: (Num a,Num b) -> (a -> b) -> Polinomio a -> Polinomio b
    fmap f (Cons x) = Cons $ f x
    fmap f (Pol x g p) = Pol (f x) g (fmap f p)

从编译器获取它不起作用:

Polinomio_GADT.hs:31:13:
Predicate `(Num a, Num b)' used as a type
In the type signature for `fmap':
  fmap :: (Num a, Num b) -> (a -> b) -> Polinomio a -> Polinomio b
In the instance declaration for `Functor Polinomio'

知道如何解决吗?

4

1 回答 1

4

你的数据类型是

data Polinomio a where
    Pol  :: (Num a) => a -> Integer -> Polinomio a -> Polinomio a
    Cons :: (Num a) => a -> Polinomio a

现在看看你对 Functor 的定义

instance Functor Polinomio where
    fmap f (Cons x) = Cons $ f x
    fmap f (Pol x g p) = Pol (f x) g (fmap f p)

由于 GADT 约束,ghc 能够推断出约束Num ax但问题在于推断f为type的不受限制的功能。因此它无法限制.f :: a -> b, x :: Num a => af xbf xNum b => bCons

所以正如丹尼尔所指出的,你不能给你的 Functor 类添加约束。您可以像这里一样定义自己的受限 Functor 类,也可以使用 rmonad 中的RFunctor

于 2013-06-22T16:07:47.360 回答