【问题标题】:SMLNJ Insertion Sort Operator and Operand dont agree errorSMLNJ 插入排序运算符和操作数不一致错误
【发布时间】:2017-12-12 02:22:23
【问题描述】:

我在 SML 中制作插入排序代码,这里是

fun compare(x:real, y:real, F) = F(x, y);
fun isEqual(x:real, y:real) = ((x <= y) andalso (x >= y));

fun rinsert(x: real, [], F) = [x]
    |rinsert(x, (y::ys), F) =
    if isEqual(x, y) then rinsert (x, ys, F)
    else if compare(x, y, F) then x::y::ys
            else y::(rinsert (x, ys, F));

fun rinsort([], F) = []
    |rinsort(x::xs, F) = rinsert(x, (rinsort(xs, F), F));

但是,在运行它时,我得到了这个错误

val isEqual = fn : real * real -> bool                                                                                                                                                               
val rinsert = fn : real * real list * (real * real -> bool) -> real list                                                                                                                             
stdIn:12.27-12.58 Error: operator and operand don't agree [tycon mismatch]                                                                                                                           
  operator domain: real * real list * (real * real -> bool)                                                                                                                                          
  operand:         'Z * ('Y list * 'X)                                                                                                                                                               
  in expression:                                                                                                                                                                                     
    rinsert (x,(rinsort (<exp>,<exp>),F))

我了解 rinsort 错误地调用了 rinrt,但我不知道如何解决它。

【问题讨论】:

  • rinsert 接受多少个参数?你和几个人打电话?
  • rinsert 接受三个参数,一个实数、一个列表和一个运算符(如 op
  • 我不明白您所说的“应该只调用三个”是什么意思。看代码。计算论据。有几个?
  • 哇,这对我来说是一个可怕的疏忽,谢谢伙计。现在工作得很好

标签: sml insertion-sort smlnj operand


【解决方案1】:

如果它有用,这是一个示例,说明您的代码应该如何与 areal list 一起工作:

fun compare(x:real, y:real, F) = F x y;
fun isEqual(x:real, y:real) = ((x <= y) andalso (x >= y));

fun rinsert(x: real, [], F) = [x]
    |rinsert(x, (y::ys), F) =
    if isEqual(x, y) then rinsert (x, ys, F)
    else if compare(x, y, F) then x::y::ys
            else y::(rinsert (x, ys, F));

fun rinsort([], F) = []
    |rinsort(x::xs, F) = rinsert(x, rinsort(xs, F), F);

val funcComp = fn r1 : real => fn r2 : real => if r1 < r2 then true else false;
val l : real list = [1.0, 3.8, 5.6, 3.8, 4.4, 5.6, 6.3, 5.5, 4.6, 8.1];
val b = rinsort(l, funcComp);

【讨论】:

  • if r1 &gt; r2 then false else true 更好地表达为r1 &lt;= r2
  • 是的,但不完全是,因为isEqual 已经检查了它们的相等性。无论如何,您的版本肯定更好理解。
  • 你不应该这样比较真实的。您可能对 Why can't I compare reals in Standard ML? 感兴趣考虑使用 Real.== 或 epsilon 测试。
【解决方案2】:

一些一般性反馈:

  • 函数compare只是用来切换F的参数顺序,所以你还不如直接引用F本身。

  • isEqual 函数有点糟糕。由于reals are not equality types in SML 是有原因的,请尽量避免这样比较它们。事实证明,为了对实数进行排序,您只需要&lt;=,而不需要=

  • 函数rinsert 具有严格的: real 类型注释,因为您的插入排序,在将比较运算符F 作为参数时,这些注释是不必要的,也可能是通用的(多态的)。

  • 您可能希望将参数 F 称为更具描述性的名称,例如 cmpleq 或任何能提醒您其用途的名称。

下面是一个示例,说明如何也可以创建插入排序函数:

fun sort leq xs =
    let fun insert (x, []) = [x]
          | insert (x, y::ys) =
              if leq (x, y)
              then x::y::ys
              else y::insert (x, ys)
    in List.foldl insert [] xs
    end

它的类型为('a * 'a -&gt; bool) -&gt; 'a list -&gt; 'a list。这与例如SML/NJ 内置ListMergeSort.sort。我选择 sortcurried 是因为您可能希望通过部分函数应用程序对其进行专门化,例如,

val realsort = sort (op <=) : real list -> real list
val stringsort = sort (op >) : string list -> string list

但是我已经让嵌入的帮助函数insert 不进行curried,因为List.foldl 采用类型为('a * 'b -&gt; 'b) 的函数,即(x, ys) 的元组并返回修改后的ysx插入。

您可能需要考虑哪些属性可以测试您的函数是否排序。一个属性可能是排序列表中的所有列表元素都按照比较运算符leq 指定的顺序。

fun sorted_prop _ [] = true
  | sorted_prop _ [_] = true
  | sorted_prop leq (x::y::xs) = leq (x, y) andalso sorted_prop leq (y::xs)

另一个属性可能是未排序列表中的每个元素都存在于排序列表中。如果您不假设 x 具有相等类型 (''a),则后一个属性可能很难测试。但是你可以专门在测试中这样做。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-28
    • 2020-05-19
    • 1970-01-01
    相关资源
    最近更新 更多