18

我想定义一个+-+在此工作的运算符(称为它):

if a,b are Char    => a +-+ b = [a][b]
if a,b are Integer => a +-+ b = a+b

我试过:

class Summable a where
    (+-+)       :: a -> a -> b

instance Summable Integer where
    a +-+ b     = a + b

instance Summable Char where
    a +-+ b     = [a] ++ [b]

但我得到了错误:

Couldn't match type `b' with `Integer'....
Couldn't match type `b' with `[Char]' ....

是否有可能做到这一点?如何?

4

1 回答 1

25

问题是类型变量b不能从实例中确定,即使它是固定的。(有一个像这样的自由变量需要函数返回任何类型的东西,即undefined。)

你能给出+-+类型a -> a -> a吗?如果是这样,那就这样做。(但看起来这是不可能的。)

否则,您可以使用功能依赖项,以便实例指定结果类型或类型系列,以便实例化的属性之一是结果类型。

对于功能依赖,代码可能如下所示:

{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}

class Summable a result | a -> result where
  (+-+) :: a -> a -> result

instance Summable Char String where
  a +-+ b = [a] ++ [b]

instance Summable Integer Integer where
  a +-+ b = a + b

对于类型族,它会像:

{-# LANGUAGE TypeFamilies #-}

class Summable a where
  type Result a
  (+-+) :: a -> a -> Result a

instance Summable Char where
  type Result Char = String
  a +-+ b = [a] ++ [b]

instance Summable Integer where
  type Result Integer = Integer
  a +-+ b = a + b

(感谢 Vitus 和 Vladimir Matveev 修复了我犯的各种错误!:))

于 2012-08-22T15:41:00.593 回答