【发布时间】:2023-04-18 23:47:01
【问题描述】:
我正在尝试在类型 T 上定义多态函数 sum,其中类型 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),因为我会在稍后处理类型不匹配的情况。
【问题讨论】:
-
那些不是测试用例。测试用例将预期值与实际值进行比较。您还没有说明它们如何或为什么不起作用,因此只能通过猜测您认为错误是什么来帮助您。
-
我编辑了问题并使其更加清晰。
-
变得不那么清楚了:毫无疑问。您的测试不起作用(
L L([2, 3, 4]可能应该是L [L [2, 3, 4]]并且您无法比较实数是否相等;您是否真的阅读了我的答案?)。而且由于您编辑了主要代码,因此您没有关于L模式的递归的基本案例,这使得它比您编辑它之前更漂亮但更破碎。 * 不太适合逐渐消除错误消息的来回过程。你可能需要导师或耐心。