Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 类型类定义,其函数取决于其他类型_Haskell_Typeclass - Fatal编程技术网

Haskell 类型类定义,其函数取决于其他类型

Haskell 类型类定义,其函数取决于其他类型,haskell,typeclass,Haskell,Typeclass,Haskell还是个新手,我遇到了以下问题: class MixedRing b where (.+.) :: b -> b -> b (.*.) :: (Num a) => b -> a -> b (./.) :: (Num a) => b -> a -> b 我试图定义一些类型类来推广一系列函数,这些函数使用高斯消去法来求解线性方程组 给定一个线性系统 M x = k 元素m(i,j)\elem m的类型a可以不同于

Haskell还是个新手,我遇到了以下问题:

class MixedRing b where
    (.+.) :: b -> b -> b
    (.*.) :: (Num a) => b -> a -> b
    (./.) :: (Num a) => b -> a -> b
我试图定义一些类型类来推广一系列函数,这些函数使用高斯消去法来求解线性方程组

给定一个线性系统

M x = k
元素
m(i,j)\elem m
的类型
a
可以不同于
x
k
的类型
b
。为了能够解决该系统,
a
应该是
Num
的一个实例,
b
应该具有带
b
的乘法/加法运算符,如下所示:

class MixedRing b where
    (.+.) :: b -> b -> b
    (.*.) :: (Num a) => b -> a -> b
    (./.) :: (Num a) => b -> a -> b
现在,即使在这些运算符的最简单的实现中,我也会得到
无法推导出a~Int。a是一个刚性类型变量
错误(让我们忘记
/
,它需要
分数


我已经阅读了一些关于类型类的教程,但我找不到任何指向实际错误的指针。

您的实现不够多态

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

换言之:类变量正是必须在实例定义中用具体类型实例化的变量

您是否尝试过:

data Wrap a = W { get :: a }

请注意,一旦
Wrap a
是一个实例,您仍然可以将其与只接受
Wrap Int

的函数一起使用,例如:

class (Num a) => MixedRing a b where
    (.+.) :: b -> b -> b
    (.*.) :: b -> a -> b
    (./.) :: b -> a -> b
您需要
MultiParamTypeClasses
扩展名


顺便说一句,在我看来,你试图建模的数学结构实际上是模块,而不是环。对于上面给出的类型变量,可以说
b
是一个
a
-模块。

让我们看看您必须为
(.*)
提供的实现类型,以使
Wrap
成为
混合
的一个实例。将方法类型中的
Wrap
替换为
b
,将产生

(.*.) :: Num a => Wrap -> a -> Wrap
由于
Wrap
Int
同构,因此不必考虑使用
Wrap
get
进行包装和展开,让我们将目标简化为找到

(.*.) :: Num a => Int -> a -> Int
(你看到这并没有让挑战变得更容易或更难,不是吗?)

现在,请注意,这样的实现将需要能够对碰巧位于type类
Num
中的所有类型
a
进行操作。(这就是这种类型中的类型变量所表示的:通用量化。)注意:这与说您的实现本身可以选择要操作的
a
不同(实际上,这是相反的);然而,这就是您在问题中的建议:应该允许您的实现选择
Int
作为
a
的选择

现在,当您想用
(*)
类型
Int
(*)
来实现这个特定的
(*)
时,我们需要以下形式的东西

n .*. s = n * f s


我想不出一个函数能够以一种有意义的方式将任意的
Num
-type
a
转换为
Int
。因此,我要说的是,没有任何有意义的方法可以使
Int
(因此,
Wrap
)成为
混合的一个实例;也就是说,实例的行为与您可能期望的不同。

已经有一个包定义了这个类:您可以在那里看一看。是的,我已经尝试过这个-有限制和没有限制
instance(Num a)=>MixedRing(Wrap a)其中
-没有帮助。但这是因为您实现了。*.,请参阅
dblhelix
注释。不知道有多参数类型的类,这是有效的。你是对的,当然,模块是正确的术语。物理学家,这里不是数学家,近似值就足够了;)很好的解释。实际上有两个错误:第一,不能在实例定义中实例化a(来自类定义)和b)方法。*。实现的是导致b=a,因此与。*的类型相矛盾。在课堂上给出。谢谢你的精彩解释。连同其他答案以及指向
VectorSpace
包的链接,这澄清了问题。
f :: Num a => a -> Int