我试图在类型T上定义多态函数和,其中类型T可以是int,real或类型T的列表.int和real的情况的总和应该按预期工作 . 对于T列表的情况,它应该返回两个列表的相应元素的总和(列表的长度应该相同) .
例子:
sum (INT 2, INT 3) = INT 5
sum (REAL 2.3, REAL 3.4) = REAL 5.7
sum(L [2, 3, 4], L [3, 4, 5]) = L [5, 7, 9]
sum(L L([2, 3, 4], [2, 3, 4]), L ([3, 4, 5], [3, 4, 5]) = L ([5, 7, 9], [3, 4, 5])
我写的功能如下:
datatype T = INT of int | REAL of real | L of T list;
fun sum (x:T, x':T) = case (x, x') of
(INT n, INT n') => INT (n + n')
| (REAL n, REAL n') => REAL (n + n')
| (L (x :: xs), L (y :: ys)) => L ((sum (x, y)) :: (sum (L xs, L
ys))
| (_,_) => REAL (0.0);
但是对于上面的函数,我得到了错误:
构造函数应用于不正确的参数 .
expects: _ * [??? list]
but got: _ * [???]
in: :: (sum (x, y), sum (L xs, L ys))
unhandled exception: Fail: compilation aborted: parseAndElaborate reported errors
因此我通过添加nil来改变我的代码,如下所示 . 据我所知,错误的原因是cons运算符试图将T(INT或REAL)最终连接到T(INT或REAL)为(sum(x,y),sum(L xs) ,L ys))最终将通过递归调用INT或REAL来评估 . 因此,我最后通过添加nil(空列表)来更改我的代码
fun sum (x:T, x':T) = case (x, x') of
(INT n, INT n') => INT (n + n')
| (REAL n, REAL n') => REAL (n + n')
| (L (x :: xs), L (y :: ys)) => L ((sum (x, y)) :: (sum (L xs,
L ys)) :: nil)
| (_,_) => REAL (0.0);
但是对于这种情况,它对INT和REAL的行为正确,但对于多态列表则不行 . 它对INT和REAL的行为正确(因为它们更容易实现) . 对于列表部分,我想cons运算符存在一些问题,我无法找出解决方案 . 我执行的测试用例及其输出如下:
sum (L([INT(1)]), L([INT(3)]));
val it = L [INT 4,L []] : T
sum (L([INT(1),INT(2)]), L([INT(3),INT(4)]));
val it = L [INT 4,L [INT #,L #]] : T
P.S:请忽略最后一种情况(,)=> REAL(0.0),因为我稍后会处理类型不匹配的情况 .
1 回答
REAL 0.0
似乎是一个问题 .例如,为什么
sum (INT 2, L [INT 3])
应该REAL 0.0
?为什么
sum (INT 2, REAL 3.0)
应该REAL 0.0
?如果对您的域有意义,可以考虑添加
INT
和REAL
的备用,或者更好的是,考虑将sum
函数更改为可能返回一个总和,如果它可以在树的所有级别上有意义地计算,即val sum : T * T -> T option
. 它归结为错误处理 .您的示例看起来像测试:
除了
T
不是相等类型,因为它包含real
,因此当您遇到real
时,需要编写自己的使用epsilon test (nearlyEqual)的相等运算符,例如:你的一些角落情况可能看起来像