Class haskell制造(a类)其他类的实例';
同样是哈斯凯勒和哈斯凯勒特 我仍然有一个问题,我真的不知道什么时候使用Class haskell制造(a类)其他类的实例';,class,haskell,types,Class,Haskell,Types,同样是哈斯凯勒和哈斯凯勒特 我仍然有一个问题,我真的不知道什么时候使用(a类)=>a,类型或 类型a其中类型是“联合类型”,例如Val和ExprTree 现在,我想通过添加几个实例使我的数据类型ExprTree更加通用: import Ratio data Fun = Add|Sub|Mul|Div|Pow deriving (Eq,Ord) instance Show Fun where show Add = "+" show Sub = "-" show Mu
(a类)=>a
,类型
或
类型a
其中类型是“联合类型”,例如Val
和ExprTree
现在,我想通过添加几个实例使我的数据类型ExprTree
更加通用:
import Ratio
data Fun = Add|Sub|Mul|Div|Pow
deriving (Eq,Ord)
instance Show Fun where
show Add = "+"
show Sub = "-"
show Mul = "*"
show Div = "/"
show Pow = "^"
type Label = Rational
type Var = String
class Eval e where
eval :: (Num a) => e -> a -> a
data ExprTree a = Leaf {lab::Label, val::Val a}
| Node {lab::Label, fun::Fun, lBranch::ExprTree a, rBranch::ExprTree a}
deriving(Eq,Ord)
data Val a = Num a | Var String deriving (Eq, Ord, Show)
instance(Num a)=>Num(ExprTree a)其中
...
fromInteger i=Leaf(0%1)i--实例定义Num
的问题是您说您正在显示
任何ExprTree
都是Num
(表示任何类型a
)的一个实例,但是
您展示了exprtreeinteger
是Num的一个实例。换句话说,您不能
如果不想像这样声明实例,请专门化该类型变量
这:
Show实例也有类似的问题。你没有展示你是怎么做的
exprtreea
是任何任意a
的Show实例,您正在显示它
仅适用于已经是Show实例的a
s。换句话说,你会
需要更改实例声明,如下所示:
instance (Show a) => Show (ExprTree a) where
...
为了让它工作
Eval实例声明中的第三个错误来自一些无关的东西
很普通,基本上你是在使用a->e->e类型的函数
您正在返回第一个参数a
。Haskell很困惑,因为你
鉴于没有迹象表明a
和e
是同一类型,因此没有理由
它应该接受a
类型的值作为返回类型。(这可能只是一个例子
你可能会有点困惑。eval
有签名(nume)=>e->a->
a、 但是您已经在实例声明中将第一个变量命名为a
Val a
)
所以,排除第三审声明,你的问题似乎是
向Haskell承诺,您将为
非常通用的类型(如任何a
都使用exprtreea
),但随后您就违背了
通过要求a
是某种更具体的类型,如Integer来保证fromInteger
的问题是i
需要转换为Val a
instance Num a => Num (ExprTree a) where
-- ...
fromInteger i = Leaf (0%1) (Val (fromInteger i))
Val
包装器使其成为Val
;内部fromInteger
创建一个a
,这是调用方指定的类型,我们知道可以使用fromInteger
创建该类型,因为Num a
约束来自Integer
。请密切注意最后一点:这是类型类背后的原因。Num a=>
约束确保,给定a
,我们知道可以对其使用任何Num
实例方法
另一个问题与此相反:您正在调用show
,但是您没有做任何事情来确保show
在a
上有意义
instance Num a => Num (ExprTree a) where
-- ...
fromInteger i = Leaf (0%1) (Val (fromInteger i))
instance Show a => ExprTree a where
show (Leaf _ a) = show a -- this works now because we told it a is show-able
-- ...
Eval
的问题略有不同:a
只是在没有任何源代码的情况下出现,因此编译器对它一无所知。特别是,eval a\ua
要求e
必须是有效的a
——但是a
是未知的,因此编译器正确地说“什么?”。对于这一点,你需要考虑你真正想要做什么;最简单的解决方案是去掉e
并在任何地方使用a
,但这真的是你想要的吗?我不认为那种eval
是你想要的。它太笼统了,因为它承诺对任何a
都有效,只要它在Num
中。
instance Show a => ExprTree a where
show (Leaf _ a) = show a -- this works now because we told it a is show-able
-- ...