我正在尝试编写一个简单的add函数,该函数接受两个真实列表并将匹配的索引加在一起并生成一个真实列表,但是由于某种原因,我无法让它接受真实列表作为参数,而只能整数列表。
fun add (nil, _) = nil
| add (_, nil) = nil
| add (a :: b, x :: y) = (a + x) :: add (b,y)
当我尝试运行测试输入时,val addTest = add([1.0, 2.0, 3.0], [0.1, 0.2, 0.3]);
会给我:
Error: operator and operand do not agree [tycon mismatch]
operator domain: int list * int list
operand: real list * real list
我很好奇为什么SML默认使用int列表,即使“ +”操作数同时用于实数和整数。它不应该接受`列表,而不仅仅是int列表吗?
答案 0 :(得分:2)
是的,+
(以及其他算术运算符)被重载,但不是参数多态性。
因此您可以执行1.0 + 1.0
和1 + 1
,它们分别给出 real 和 int 。
但是fun f x y = x + y
可以推断出其中一个,因此编译器默认为 int 重载。
除了您自己的答案外,您还可以在代码中使用单个: real
:
fun add ([], _) = []
| add (_, []) = []
| add (x::xs, y::ys) = (x + y : real) :: add (xs, ys)
,它将推断您在所有其他地方也必须表示 real 。
您可以将此操作概括为一个称为zipWith
的操作:
- fun zipWith f [] _ = []
| zipWith f _ [] = []
| zipWith f (x::xs) (y::ys) = f (x, y) :: zipWith f xs ys
> val ('a, 'b, 'c) zipWith = fn :
('a * 'b -> 'c) -> 'a list -> 'b list -> 'c list
- val add = zipWith (op + : real * real -> real)
> val add = fn : real list -> real list -> real list
- add [1.0, 2.0, 3.0] [4.0, 5.0, 6.0];
> val it = [5.0, 7.0, 9.0] : real list
答案 1 :(得分:1)
我发现在这种情况下SML的默认行为是默认为int行为,因此,如果您有一个适用于实数或int的操作数,它将被评估为int。对于上述方法,我可以通过将元组中的参数指定为真实列表来获得所需的行为,如下所示:
fun add (nil, _) = nil
| add (_, nil) = nil
| add (a::b : real list, x::y : real list) = (a + x) :: add (b,y)