SML仅在应为真实列表时才接受int列表

时间:2019-02-26 03:26:58

标签: sml

我正在尝试编写一个简单的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列表吗?

2 个答案:

答案 0 :(得分:2)

是的,+(以及其他算术运算符)被重载,但不是参数多态性

因此您可以执行1.0 + 1.01 + 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)