我试图将给定列表的元素加倍,但是收到错误"
该表达式预计具有类型
''列表'
但这里有类型
' INT'
"
在定义新列表时
let list1 = [5;10;15;20;25;30]
let rec doubleListElements list =
match list with
|[]-> 0
|head::tail ->
let doubledList = [head*2::doubleListElements tail]
0
let printList = doubleListElements list1
printfn "%A" printList
我对f#很新,并且不完全理解事情是如何工作的,我更习惯于面向对象的方法
答案 0 :(得分:3)
您问题中的功能可以进行一些更改:
let rec doubleListElements list =
match list with
| [] -> []
| head::tail -> head*2::doubleListElements tail
要记住的第一件重要事情是“我想要从这个功能中获得和接受什么”。在您的情况下,您的输入为int list
,所需的输出为int list
。这意味着只要函数返回值,它就必须是int list
。您的函数有两个返回值的位置:
| [] -> [] // return empty list
| head::tail ->
head*2::doubleListElements tail // return a list (but recurse)
在原始函数中,返回值始终为0
,这当然不符合int list
返回类型。
|[]-> 0 // return value
|head::tail ->
let doubledList = [head*2::doubleListElements tail]
0 // return value
在此表达式中,创建了doubledList
,但该值基本上被丢弃,因为它未使用且不是返回值。返回值是表达式中的最终值:0
。我认为这是一个非常常见的错误,因为当人们学习来自基于语句的基于语句的语言基于表达式的函数式语言时。
在这个特定的表达式中,只有最终值很重要。在基于语句的语言中,您可能在返回值之前改变了一些程序状态(这在F#中也是完全可能的,但通常可以避免可变性)。
let foo x =
let y = x + x // the value of this expression is discarded: y is unused
x * x // the value of this expression is returned
唯一的其他必要更改是不在每次递归中将返回的列表包装在另一个列表中。 head*2::doubleListElements tail
只是一个列表。 [head*2::doubleListElements tail]
与另一个列表中的列表相同,因为它包含在方括号列表文字中。在改变之后它起作用:
val printList : int list = [10; 20; 30; 40; 50; 60]
答案 1 :(得分:0)
您可以使用不同类型的数据结构,例如序列:
namespace FSharpBasics
module DoubleList =
let private list1 = [ 5; 10; 15; 20; 25; 30 ]
(*operations*)
let doubleList (list: List<int>) =
Seq.init list.Length (fun index -> list.[index] * 2)
|> Seq.toList
[<EntryPoint>]
let main argv =
doubleList list1
|> printf "%A"
System.Console.ReadKey() |> ignore
0