反转列表然后添加新项目

时间:2017-02-05 20:01:38

标签: f#

我正在尝试学习F#,并且我正在尝试创建一些简单的函数作为学习的一部分。

我创建了一个将项添加到列表然后反转结果的函数。这在Visual Studio的F#交互式窗口中非常有效。

let addThenReverse n list =
match list with
| [] -> []
| _ -> n::list |> List.rev

addThenReverse 0 [1;2;3]   //results in [3; 2; 1; 0]

但是我在编写一个能够反转列表然后向其中添加项目的函数时遇到了困难。

let reverseThenAdd n list =
    match list with
    | [] -> []
    | _ -> List.rev list |> n::list

reverseThenAdd 9 [1;2;3]  //desired result [3; 2; 1; 9]

修改 上述所需的结果应该是 [9; 3; 2; 1] 即可。那些发现这个的人做得好!

第二个函数没有编译,我收到警告'这个表达式应该有类型'列表 - > 'b list但这里有'c list'类型

我尝试的任何变种似乎都会导致其他编译错误。我假设(但不知道如何)我需要使用由“List.rev list”创建的新列表,可能是将其分配给变量。

3 个答案:

答案 0 :(得分:4)

问题是您将反转列表传递给串联表达式,并抛出编译器。你应该这样做:

let reverseThenAdd n list =
    match list with
    | [] -> []
    | _ -> n :: (List.rev list)

reverseThenAdd 9 [1;2;3]  //desired result [3;2;1;9]

表示您要将n添加到(List.rev list)

生成的列表中

答案 1 :(得分:4)

我对你期望的结果感到有些困惑。 Luiso有一个代码版本可以修复编译器,但它不符合你想要的结果。与

let reverseThenAdd n list =
    match list with
    | [] -> []
    | _ -> n :: (List.rev list)

reverseThenAdd 9 [1;2;3]  //desired result [3; 2; 1; 9]

实际结果为[9; 3; 2; 1]。如果评论是拼写错误,这实际上是您想要的结果,那么Luiso的回答是有效的。否则,addThenReversereverseThenAdd之间没有任何实质性差异,因为“添加”意味着在每种情况下都有不同的内容(附加和前置)。

请注意,我认为在这两种情况下,第一种情况都应该是

| [] -> [n]

而不是

| [] -> []

事实上,我认为你根本不需要匹配声明。我认为数学上正确的公式是:

let addThenReverse n list = n::list |> List.rev
let reverseThenAdd n list = n::(list |> List.rev)

然后你会

addThenReverse 0 [] // result: [0]
reverseThenAdd 0 [] // result: [0]
addThenReverse 9 [1; 2; 3] // result: [3; 2; 1; 9]
reverseThenAdd 9 [1; 2; 3] // result: [9; 3; 2; 1]

<强>附录

我是表达代码的粉丝。像F#一样优雅,仍然可以编写模糊您实际尝试的代码。上面的代码可以使用,但你可以通过使用合成运算符使它更具表现力,并更多地了解语言的工作原理:

let add n list = n::list
let reverse = List.rev
let addThenReverse n = add n >> reverse
let reverseThenAdd n = reverse >> add n

这给出了与以前相同的结果,但它更清楚地表达了你正在做的事情。秉承函数式编程的精神,你告诉编译器要做什么,而不是 如何做。

答案 2 :(得分:1)

let reverseThenAdd n list = List.rev list @ [n]