You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SML不排序判断两无序列表元素频次相等的代码报错排查

问题说明

需求为判断两个无序列表是否包含完全相同的值,且各值出现次数完全一致,作业明确要求不得对列表进行排序。
原实现采用递归比较逻辑:

  • 以两列表长度不同为基准情况,直接返回false
  • 每次递归检查第二个列表l2是否包含第一个列表l1的首元素hd:
    • 若存在,移除l1首元素、l2中第一个匹配到的同值元素,对剩余部分递归调用isEqual
    • 若不存在,直接返回false
原实现代码
fun doesExist l =
    List.exists (fn x => x = true) l
; (* returns true if there's at least one 'true' in the list of bool *)

fun getFirstIndex target (a::b) index =
    if (a::b) = []
    then index
    else
        if target = a
        then index
        else getFirstIndex target b index+1
; (* returns the index of the first element = to 'target', in this case 'true', 
looking into the list (a::b) *)

fun delete (_,   nil) = nil
  | delete (0, _::xs) = xs
  | delete (i, x::xs) = x::delete(i-1,xs)
; (* should delete an element from a list, given the index gotten with the function above *)

fun isEqual [] [] = true
 | isEqual [] _ = false
 | isEqual _ [] = false
 | isEqual _ _ = false
 | isEqual l1 l2 =
    if List.length l1 <> List.length l2
    then false
    else
        if doesExist(List.map (fn n => n = hd l1) l2)
        then 
            isEqual(tl l1, delete(getFirstIndex(true, l2, 0), l2))
        else
            false
; (* this function puts altogether and should return either false or true *)
预期测试用例输出
isEqual [] []; (* true *)
isEqual [1] [1]; (* true *)
isEqual [1,4,2,8] [8,1,4,2]; (* true *)
isEqual [1,2,4,3] [11,24,56,7]; (* false *)
isEqual [7,5,12,88] [7,88,12,5,5]; (* false *)
isEqual [7,5,12,88,88] [7,88,12,5,5]; (* false *)
isEqual [7,5,12,88] [7,5,12,88,13,15]; (* false *)
编译报错信息
error: Type error in function application.
   Function: delete : int * 'a list -> 'a list
   Argument: (getFirstIndex (true, l2, 0), l2) :
      ((bool * ''a list * int) list -> int -> int) * ''a list
   Reason:
      Can't unify int to (bool * ''a list * int) list -> int -> int
         (Incompatible types)
Found near
  if doesExist (List.map (fn ... => ...) l2) then
  isEqual (tl l1, delete (...)) else false
es13.sml:24: error: Type of function does not match type of recursive application.
   Function:
      fun
         isEqual [] [...] = true |
            isEqual [...] ... = false |
            isEqual ... = false |
            isEqual ... = ... |
            ... : ''a list -> ''a list -> bool
   Variable: isEqual : ''a list * 'b list -> bool
   Reason: Can't unify ''a list to ''a list * 'b list (Incompatible types)
Found near
  fun
     isEqual [] [...] = true |
        isEqual [...] ... = false |
        isEqual ... = false |
        isEqual ... = ... |
        ...
Exception- Fail "Static Errors" raised
问题排查与修复

代码共存在5处问题:

  1. SML函数调用语法错误:SML中柯里化函数传参不需要将参数打包为元组,原代码递归调用isEqual(tl l1, delete(...))相当于给isEqual传入一个二元元组,和定义的“接收两个独立列表参数”的签名不匹配,触发类型错误。
  2. 运算符优先级错误:getFirstIndex target b index+1中函数调用优先级高于算术运算符,实际执行逻辑为(getFirstIndex target b index) + 1,并非预期的传入index+1作为新索引值,需要给index+1加括号修正优先级。
  3. getFirstIndex参数传递错误:该函数为柯里化定义,第一个参数为查找目标值,原代码调用时写成getFirstIndex(true, l2, 0)把三个参数打包为元组传入,完全不匹配函数签名;且原逻辑先通过List.map生成布尔列表再查找true属于冗余逻辑,可直接查找目标元素。
  4. 分支顺序错误:isEqual _ _ = false写在通用递归分支之前,所有非空双列表输入都会直接匹配该分支返回false,后续递归逻辑永远无法执行。
  5. 边界匹配缺失:getFirstIndex仅匹配了非空列表构造a::b,传入空列表时会触发匹配非穷尽错误。

修复后的完整可运行代码如下,全程未对原列表排序,符合要求:

(* 查找目标元素在列表中第一次出现的索引,不存在返回~1 *)
fun getFirstIndex target nil index = ~1
  | getFirstIndex target (a::b) index =
    if target = a
    then index
    else getFirstIndex target b (index + 1)

(* 删除列表指定索引位置的元素,索引非法时返回原列表 *)
fun delete (_, nil) = nil
  | delete (0, _::xs) = xs
  | delete (i, x::xs) = 
    if i < 0 then x::xs
    else x::delete(i-1, xs)

fun isEqual [] [] = true
  | isEqual [] _ = false
  | isEqual _ [] = false
  | isEqual l1 l2 =
    if List.length l1 <> List.length l2
    then false
    else
      let
        val target = hd l1
        val idx = getFirstIndex target l2 0
      in
        if idx = ~1
        then false
        else isEqual (tl l1) (delete (idx, l2))
      end

上述代码可全部通过列出的测试用例。

内容的提问来源于stack exchange,提问作者Dovday

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 03:51:23