使用取决于其他类型的函数键入类定义

时间:2011-12-16 12:15:10

标签: haskell typeclass

Haskell还是新手,我已经碰到了以下内容:

我试图定义一些类型类来概括一堆使用高斯消元法求解线性方程组的函数。

给定一个线性系统

M x = k

元素a的类型m(i,j) \elem M可能与bx的类型k不同。为了能够解决系统问题,a应该是Num的实例,而b应该有b的乘法/加法运算符,如下所示:

class MixedRing b where
    (.+.) :: b -> b -> b
    (.*.) :: (Num a) => b -> a -> b
    (./.) :: (Num a) => b -> a -> b

现在,即使在这些运算符的最简单实现中,我也会遇到Could not deduce a ~ Int. a is a rigid type variable错误(让我们忘记需要./.的{​​{1}})

Fractional

我已经阅读了几个关于类型类的教程,但我找不到指向实际出错的指针。

3 个答案:

答案 0 :(得分:10)

让我们看看您必须为(.*.)提供Wrap MixedRing实例的实施类型。在方法类型中用Wrap代替b会产生

(.*.) :: Num a => Wrap -> a -> Wrap

由于WrapInt同构,并且不必考虑使用Wrapget进行包装和解包,让我们减少查找

(.*.) :: Num a => Int -> a -> Int

(你知道这不会让挑战变得更容易或更难,不是吗?)

现在,请注意,这样的实现需要能够对类型类a中恰好位于的所有类型Num进行操作。 (这就是这种类型的类型变量表示:通用量化。)注意:这说明你的实现本身可以选择a进行操作,这是不一样的(实际上是相反的);但这似乎是您在问题中建议的:应该允许您的实施选择Int作为a的选择。

现在,由于您希望针对类型(.*.)的值(*)实现此特定Int,我们需要一些形式

n .*. s = n * f s

f :: Num a => a -> Int

我无法想象一个能够以有意义的方式从仲裁Num - 类型a转换为Int的函数。因此,我要说,没有任何有意义的方法可以使Int(以及Wrap)成为MixedRing的实例;也就是说,实例的行为并不像你希望的那样。

答案 1 :(得分:6)

如下:

class (Num a) => MixedRing a b where
    (.+.) :: b -> b -> b
    (.*.) :: b -> a -> b
    (./.) :: b -> a -> b

您需要MultiParamTypeClasses扩展名。

顺便说一句,在我看来,您尝试建模的数学结构实际上是模块,而不是环。使用上面给出的类型变量,可以说 ba - 模块

答案 2 :(得分:2)

您的实现不够多态。

规则是,如果在类定义中编写a,则不能在实例中使用具体类型。因为实例必须符合类和承诺接受任何a Num的类。

换句话说:正是类变量必须在实例定义中使用具体类型进行实例化。

你试过了吗?

data Wrap a = W { get :: a }

请注意,Wrap a是一个实例,您仍然可以将其与仅接受Wrap Int的函数一起使用。