2017-07-07 92 views
0

林在SML使插入排序的代码,这是SMLNJ插入排序操作和操作数不同意错误

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不正确地调用rinsert,但我不知道如何解决它。

+0

'rinsert'需要多少个参数?你打了几个电话? – melpomene

+0

rinsert需要三个参数,一个实数,一个列表和一个运算符(如op <)。它应该只是叫三个 – small502

+0

我不明白你的意思是“*它只应该叫三*”。看代码。计算参数。那里有多少? – melpomene

回答

0

如果它是有用的,这是如何您的代码应与工作的例子的real 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); 
+0

'如果r1> r2,那么false否则true'最好表示为'r1 <= r2'。 –

+0

是的,但不完全是因为'isEqual'已经检查它们的等式。无论如何,你的版本肯定更好理解。 –

+1

你不应该比较那样的实物。您可能对[为什么我无法比较标准ML中的实数?]感兴趣[(https://stackoverflow.com/questions/41394992/why-cant-i-compare-reals-in-standard-ml)考虑使用' Real。=='或者一个epsilon测试。 –

0

一些一般性的反馈:

  • 功能compare的目的只是为了给切换参数F的顺序,所以你不妨直接参考F

  • 函数isEqual有点不好。由于reals are not equality types in SML出于某种原因,请尽量避免将它们比较。事实证明,为了分类实物,你只需要<=而不是=

  • 功能rinsert有严格: real类型的注释是不必要的,因为你插入排序,采取比较运算F作为参数,很可能会成为通用(多态)。

  • 您可能想要调用参数F一些更具描述性的东西,如cmp,leq或任何提醒您其目的。

这里有一个如何我们也可以做一个插入排序函数的一个例子:

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 -> bool) -> 'a list -> 'a list。这与例如SML/NJ的内置ListMergeSort.sort。我选择sortcurried因为你可能想通过局部的功能应用,例如专攻它,

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

,但我已经让嵌入式辅助函数insert因为List.foldl被uncurried需要一个函数('a * 'b -> 'b)类型,即(x, ys)的元组,并且返回修改后的ys和插入的x

您可能想要考虑哪些属性可以测试您的函数进行排序。一个属性可能是排序列表中的所有列表元素都是由比较运算符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),则后者属性可能难以测试。但你可以在测试中专门做到这一点。