SML Create 函数接收元组列表和 return 列表以及每对的总和
SML Create function receives list of tuples and return list with sum each pair
我正在学习标准 ML,我必须做的一项练习是编写一个名为 opPairs 的函数,该函数接收一个 int 类型的元组列表,returns 一个包含每个元组之和的列表一对。
示例:
input: opPairs [(1, 2), (3, 4)]
output: val it = [3, 7]
这些是我的尝试,没有编译:
尝试 1
type T0 = int * int;
fun opPairs ((h:TO)::t) = let val aux =(#1 h + #2 h) in
aux::(opPairs(t))
end;
The error message is:
Error: unbound type constructor: TO
Error: operator and operand don't agree [type mismatch]
operator domain: {1:'Y; 'Z}
operand: [E]
in expression:
(fn {1=1,...} => 1) h
尝试 2
fun opPairs2 l = map (fn x => #1 x + #2 x ) l;
The error message is: Error: unresolved flex record (need to know the names of ALL the fields
in this context)
type: {1:[+ ty], 2:[+ ty]; 'Z}
第一次尝试有一个拼写错误:定义了 type T0
,其中 0
为零,但随后在模式中引用了类型 TO
,其中 O
是字母 O。这消除了“operand and operator do not agree”错误,但还有一个问题。模式 ((h:T0)::t)
不匹配空列表,因此会出现“ 匹配非穷举 ” 警告,其中包含已更正的类型标识符。这在使用该函数时表现为异常,因为代码需要在到达输入末尾时匹配空列表。
第二次尝试需要为元组使用类型。这是因为元组访问器 #n
需要知道它访问的元组的类型。要解决此问题,请向匿名函数提供元组参数的类型:
fun opPairs2 l = map (fn x:T0 => #1 x + #2 x) l;
但是,使用 #1
、#2
等访问元组字段确实是不好的做法;改用模式匹配。这是一种更简洁的方法,更像是第一次尝试,但充分利用了模式匹配:
fun opPairs nil = nil
| opPairs ((a, b)::cs) = (a + b)::(opPairs cs);
这里,opPairs
returns 当输入为空列表时为空列表,否则模式匹配提供要添加的字段值a
和b
cond 递归到输出。当到达最后一个元组时,cs
是空列表,然后 opPairs cs
也是空列表:然后将各个元组总和放入该空列表以创建输出列表。
为了扩展 exnihilo 的回答,一旦您熟悉了使用显式递归和模式匹配的解决方案类型 (opPairs ((a, b)::cs) = ...
),您就可以开始使用列表组合器概括该解决方案:
val opPairs = map op+
我正在学习标准 ML,我必须做的一项练习是编写一个名为 opPairs 的函数,该函数接收一个 int 类型的元组列表,returns 一个包含每个元组之和的列表一对。 示例:
input: opPairs [(1, 2), (3, 4)]
output: val it = [3, 7]
这些是我的尝试,没有编译:
尝试 1
type T0 = int * int;
fun opPairs ((h:TO)::t) = let val aux =(#1 h + #2 h) in
aux::(opPairs(t))
end;
The error message is:
Error: unbound type constructor: TO
Error: operator and operand don't agree [type mismatch]
operator domain: {1:'Y; 'Z}
operand: [E]
in expression:
(fn {1=1,...} => 1) h
尝试 2
fun opPairs2 l = map (fn x => #1 x + #2 x ) l;
The error message is: Error: unresolved flex record (need to know the names of ALL the fields
in this context)
type: {1:[+ ty], 2:[+ ty]; 'Z}
第一次尝试有一个拼写错误:定义了 type T0
,其中 0
为零,但随后在模式中引用了类型 TO
,其中 O
是字母 O。这消除了“operand and operator do not agree”错误,但还有一个问题。模式 ((h:T0)::t)
不匹配空列表,因此会出现“ 匹配非穷举 ” 警告,其中包含已更正的类型标识符。这在使用该函数时表现为异常,因为代码需要在到达输入末尾时匹配空列表。
第二次尝试需要为元组使用类型。这是因为元组访问器 #n
需要知道它访问的元组的类型。要解决此问题,请向匿名函数提供元组参数的类型:
fun opPairs2 l = map (fn x:T0 => #1 x + #2 x) l;
但是,使用 #1
、#2
等访问元组字段确实是不好的做法;改用模式匹配。这是一种更简洁的方法,更像是第一次尝试,但充分利用了模式匹配:
fun opPairs nil = nil
| opPairs ((a, b)::cs) = (a + b)::(opPairs cs);
这里,opPairs
returns 当输入为空列表时为空列表,否则模式匹配提供要添加的字段值a
和b
cond 递归到输出。当到达最后一个元组时,cs
是空列表,然后 opPairs cs
也是空列表:然后将各个元组总和放入该空列表以创建输出列表。
为了扩展 exnihilo 的回答,一旦您熟悉了使用显式递归和模式匹配的解决方案类型 (opPairs ((a, b)::cs) = ...
),您就可以开始使用列表组合器概括该解决方案:
val opPairs = map op+