【问题标题】:SML only accepting int list when it should be a real listSML 仅在它应该是真实列表时接受 int 列表
【发布时间】:2019-02-26 03:26:57
【问题描述】:

我正在尝试编写一个简单的添加函数,它接受两个真实列表并将匹配的索引添加在一起并生成一个真实列表,但由于某种原因,我无法让它接受真实列表作为参数,而只是int 列表。

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 列表,即使“+”操作数同时用于实数和整数。它不应该接受 `a list 而不仅仅是 int 列表吗?

【问题讨论】:

    标签: sml


    【解决方案1】:

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

    所以你可以做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)
    

    它会推断你在所有其他地方也必须是真实


    你可以把这个操作概括为一个叫做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
    

    【讨论】:

      【解决方案2】:

      我发现在这种情况下 SML 的默认行为是默认为 int 行为,因此如果您有一个适用于实数或整数的操作数,它将被评估为 int。至于上面的方法,我可以通过将元组中的参数指定为真正的列表来获得我想要的行为,如下所示:

      fun add (nil, _) = nil
        | add (_, nil) = nil
        | add (a::b : real list, x::y : real list) = (a + x) :: add (b,y)
      

      【讨论】:

        猜你喜欢
        • 2019-05-08
        • 2018-12-05
        • 1970-01-01
        • 2016-07-29
        • 2016-02-03
        • 1970-01-01
        • 2018-03-14
        • 2010-10-14
        • 1970-01-01
        相关资源
        最近更新 更多