我正在试图找出为什么我得到的错误低于我对正确实施我的方法感兴趣。
我有以下f#代码,它们应该将元组列表取消配对到包含元组中所有项目的列表中,如下所示:
let unpair l =
let rec loop acc l =
match l with
| [] -> acc
| (x,y)::tl ->
loop (acc @ x @ y) tl
loop [] l
//should print:
// [1 2 3 4 5 6]
printf "["
List.iter (printf "%A") (unpair [(1, 2); (3, 4); (5, 6)])
printfn "]"
调用unpair时,我的每个int都会出现以下错误: 该表达式应该具有类型'列表,但这里有类型int
为什么期待'列表?
答案 0 :(得分:4)
问题出在以下表达式
中acc @ x @ y
@
用于将list
值组合在一起,但此处x
和y
的类型为int
。你要找的是::
运算符,它会将项添加到列表中。此外,您正在该表达式中向后构建列表。使用以下内容,它应该解决您的问题
x :: y :: acc
答案 1 :(得分:2)
正如JaredPar所解释的,您需要使用x::acc
向累加器添加元素。如果要将元素追加到最后,可以编写acc @ [x]
,但效率非常低,因为它需要复制每个元素的整个列表。
通常的解决方案是在前面添加元素,然后在处理结束时反转列表:
let unpair l =
let rec loop acc l =
match l with
| [] -> List.rev acc // NOTE: Reverse the list here
| (x,y)::tl ->
loop (y::x::acc) tl // Add elements to the front
loop [] l
这比使用acc @ [x]
更有效率,因为它不断向前面添加元素(只需很短的时间),然后在最后创建整个列表的单个副本。
同样的功能也可以很好地和使用序列表达式有效实现:
let unpair l =
[ for x, y in l do
yield x
yield y ]