对于Haskell来说还是新手,我已经碰到了以下内容:
我试图定义一些类型类来概括一堆使用高斯消元法求解线性方程组的函数.
给定一个线性系统
M x = k
Run Code Online (Sandbox Code Playgroud)
类型a的元素m(i,j) \elem M可以与不同类型b的x和k.为了能够解决系统,a应该是一个实例,Num并且b应该有乘法/加法运算符b,如下所示:
class MixedRing b where
(.+.) :: b -> b -> b
(.*.) :: (Num a) => b -> a -> b
(./.) :: (Num a) => b -> a -> b
Run Code Online (Sandbox Code Playgroud)
现在,即使在这些运算符最简单的实现中,我也会遇到Could not deduce a ~ Int. a is a rigid type variable错误(让我们忘记./.哪些需要Fractional)
data Wrap = W { get :: Int }
instance MixedRing Wrap where
(.+.) w1 w2 = W $ (get w1) + (get w2)
(.*.) w s = W $ ((get w) * s)
Run Code Online (Sandbox Code Playgroud)
我已经阅读了几个关于类型类的教程,但我找不到指向实际出错的指针.
Ste*_*ans 10
让我们看一下为实例(.*.)制作所必须提供的实现类型.代用于在所述方法产生的类型WrapMixedRingWrapb
(.*.) :: Num a => Wrap -> a -> Wrap
Run Code Online (Sandbox Code Playgroud)
由于Wrap是同构的Int,并没有考虑包装与展开Wrap和get,让我们减少我们的目标是找到的实现
(.*.) :: Num a => Int -> a -> Int
Run Code Online (Sandbox Code Playgroud)
(你看,这不会让挑战变得更容易或更难,不是吗?)
现在,请注意这样的实现需要能够对a恰好位于类型类中的所有类型进行操作Num.(这就是这种类型的类型变量表示:通用量化.)注意:这说明你的实现本身可以选择a操作的不一样(实际上,相反); 但这就是你在问题中的建议:应该允许你的实现Int作为选择a.
现在,由于您希望(.*.)根据(*)类型的值实现此特定Int,我们需要某种形式
n .*. s = n * f s
Run Code Online (Sandbox Code Playgroud)
同
f :: Num a => a -> Int
Run Code Online (Sandbox Code Playgroud)
我不认为从arbitary转换函数Num型a以Int一种有意义的方式.因此,我要说没有有意义的方法来制作Int(并因此Wrap)一个实例MixedRing; 也就是说,实例的行为并不像您希望的那样.
怎么样的:
class (Num a) => MixedRing a b where
(.+.) :: b -> b -> b
(.*.) :: b -> a -> b
(./.) :: b -> a -> b
Run Code Online (Sandbox Code Playgroud)
你需要MultiParamTypeClasses扩展名.
顺便说一句,在我看来,你试图建模的数学结构实际上是模块,而不是环.对于上面给出的类型变量,有人说这b是一个a模块.