SML中如何向列表追加record triple?求修正similar_names函数错误
SML similar_names函数语法错误及record列表构建问题
问题说明
我在实现SML的similar_names函数时遇到语法错误,搞不懂怎么把record三元组追加到列表里。该函数需求如下:
- 接收两个参数:字符串列表的列表,以及一个类型为
{first:string, middle:string, last:string}的record - 通过
get_substitutions2函数,以输入record的first字段为匹配项,查找所有替换名 - 最终输出包含原record及所有替换名对应record的列表
我的代码
fun same_string(s1 : string, s2 : string) = s1 = s2 fun all_except_option(str, []) = NONE | all_except_option(str, x::xs) = case same_string(x, str) of true => SOME xs | false => let fun build_list(x::xs, str) = case all_except_option(str, xs) of NONE => NONE | SOME y => SOME(x::y) in build_list(x::xs, str) end fun get_substitutions2(xss, str) = let fun sub([], acc) = acc | sub(ys::yss, acc) = case all_except_option(str, ys) of NONE => sub(yss, acc) | SOME y => sub(yss, y@acc) in sub(xss, []) end fun similar_names(xss, []) = Empty | similar_names(xss, r : {first:string, middle:string, last:string}) = let fun helper (x::xs, acc) = case x of [] => acc | {first=a, middle=b, last=c} => helper(xs, {x, b, c} @ acc) in case get_substitutions2(xss,a) of NONE => NONE | SOME y => helper(y, []) end
错误信息
- foo.sml:32.45 Error: syntax error: inserting VAL - foo.sml:33.5-33.7 Error: syntax error: replacing IN with EQUALOP - foo.sml:38.5 Error: syntax error found at END
示例输入
similar_names( [["Fred", "Fredrick"], ["Elizabeth", "Betty"], ["Freddie", "Fred", "F"]], {first="Fred", middle="W", last="Smith"} )
预期输出
[{first="Fred", last="Smith", middle="W"}, {first="Fredrick", last="Smith", middle="W"}, {first="Freddie", last="Smith", middle="W"}, {first="F", last="Smith", middle="W"}]
错误分析与修正代码
你的similar_names函数存在多处语法和逻辑错误:
- 无效分支与非法值:
similar_names(xss, []) = Empty不符合需求(第二个参数应为record),且Empty不是SML合法值 - 类型匹配错误:
get_substitutions2返回字符串列表,但你在helper里错误地将字符串匹配为record - record构造与列表拼接错误:
{x, b, c}是非法的record构造方式,且单个record不能直接用@拼接列表 - 未定义变量:
case get_substitutions2(xss,a)中的a未定义,需先从输入record中解构提取
修正后的代码:
fun same_string(s1 : string, s2 : string) = s1 = s2 fun all_except_option(str, []) = NONE | all_except_option(str, x::xs) = case same_string(x, str) of true => SOME xs | false => case all_except_option(str, xs) of NONE => NONE | SOME y => SOME(x::y) fun get_substitutions2(xss, str) = let fun sub([], acc) = acc | sub(ys::yss, acc) = case all_except_option(str, ys) of NONE => sub(yss, acc) | SOME y => sub(yss, y @ acc) in sub(xss, []) end fun similar_names(xss, r : {first:string, middle:string, last:string}) = let val {first=orig_first, middle=m, last=l} = r val subs = orig_first :: get_substitutions2(xss, orig_first) fun helper [] acc = acc | helper (name::names) acc = helper names ({first=name, middle=m, last=l} :: acc) in rev (helper subs []) end
修正说明
- 移除无效分支:删除不符合需求的空列表匹配分支
- 解构输入record:从输入的
r中提取原名字、中间名、姓氏,避免重复读取字段 - 合并替换名列表:将原名字和所有替换名合并为完整的字符串列表
- 正确构建record列表:遍历每个名字构造对应record,用
::添加到列表,最后用rev保证输出顺序与预期一致 - 简化冗余代码:移除原
all_except_option中冗余的build_list函数,直接用case分支处理逻辑
内容的提问来源于stack exchange,提问作者user13017933
相关产品推荐
相关产品推荐

