【发布时间】:2018-06-05 11:43:41
【问题描述】:
我正在为 C++ 的一个子集制作解释器。解释器是用 Haskell 编写的。
我的 eval 表达式函数返回一个新环境和一个值。我将这些值编码为一种名为Val 的新类型。最小的例子:
data Val = I Integer | D Double
为了评估算术表达式,我想创建一个通用函数,它将诸如(+) 或(*) 之类的多态函数应用于包裹在Val 构造函数中的数字。
我想要这样的功能:
-- calculate :: Num a => (a -> a -> a) -> Val -> Val -> Val
calculate f (I i1) (I i2) = I (f i1 i2)
calculate f (D d1) (D d2) = D (f d1 d2)
这会产生以下错误:
tmp/example.hs:4:32: error:
• Couldn't match expected type ‘Double’ with actual type ‘Integer’
• In the first argument of ‘D’, namely ‘(f d1 d2)’
In the expression: D (f d1 d2)
In an equation for ‘calculate’:
calculate f (D d1) (D d2) = D (f d1 d2)
|
4 | calculate f (D d1) (D d2) = D (f d1 d2)
| ^^^^^^^
tmp/example.hs:4:34: error:
• Couldn't match expected type ‘Integer’ with actual type ‘Double’
• In the first argument of ‘f’, namely ‘d1’
In the first argument of ‘D’, namely ‘(f d1 d2)’
In the expression: D (f d1 d2)
|
4 | calculate f (D d1) (D d2) = D (f d1 d2)
| ^^
tmp/example.hs:4:37: error:
• Couldn't match expected type ‘Integer’ with actual type ‘Double’
• In the second argument of ‘f’, namely ‘d2’
In the first argument of ‘D’, namely ‘(f d1 d2)’
In the expression: D (f d1 d2)
|
4 | calculate f (D d1) (D d2) = D (f d1 d2)
| ^^
我无法解决这个问题。我有两个问题:
- 为什么这个程序无法进行类型检查?
- 如何正确实现
calculate?
我对普遍量化的类型只是模糊熟悉,所以如果这是问题的一部分,请温和地解释。
【问题讨论】:
-
好吧,签名表明
a可以是anythong,但这里应该是Integer,或者Double。 -
Willem:签名不是暗示该函数可以是任何函数,它接受
Num的任何实例的两个输入并返回同一实例的值?就像,(+)的类型签名是精确的Num a => a -> a -> a。还是我错过了什么? -
不是每个数字类型都是
Integer或Double。 -
当然,但是您能否详细说明为什么当程序从不使用除
Integer或Double之外的任何东西调用计算时,为什么会导致类型检查错误?我的意思是,map编译失败并不是因为它接受(a-> b)类型的函数,它可以是任何类型。这里肯定发生了其他事情,对吧?
标签: haskell typechecking