对于我正在上的课,我必须做以下练习:
实现功能
let splitAt (i : int) (l : List<'a>) : List<'a> * List<'a> = ...
将列表分为两个列表,第一个包含从位置0到位置i的所有l元素 包括在内,第二个包含所有其余元素。返回两个结果列表 在一个元组中。例如:
分割3 [3; 5; 4; -1; 2; 2] =([3; 5; 4; -1],[2; 2])
我们只能使用函数式编程来解决这些问题,因此不允许我使用预先存在的函数。
我有以下代码在我看来(在逻辑上)是正确的:
let splitAt (i:int)(l: List<'a>): List<'a> * List<'a> =
let rec loop n startlist restlist =
if n = i then
restlist * startlist
else
match startlist with
| h :: t -> loop (n+1) [t] [(restlist :: h)]
| h :: [] -> None
loop 0 l []
并在我的[<EntryPoint>]
printfn "%A" (splitAt stringlist 3)
但是,这给了我几个错误,即:
'a list
,'a list
类型都不支持运算符*
该表达式应具有类型int
,但此处具有类型char list
该表达式应具有类型List<'a>
,但此处具有类型int
答案 0 :(得分:1)
*
运算符用于声明元组类型,但是在构建元组时,请改用,
。因此,您需要restlist, startlist
。
然后您会发现还有另一种类型错误,因为match
表达式的一个分支返回了None
。这是一个选项类型,因此您返回的值应为Some
。因此,您需要Some (restlist, startlist)
。
现在您将发现另一个类型错误,即您已经声明该函数返回一个元组,但实际上它返回一个元组选项(即None
或{{1} }。因此,您的类型声明需要变为Some tuple
。
要详细了解为什么在声明元组类型而不是在(List<'a> * List<'a>) option
中使用*
,https://fsharpforfunandprofit.com/posts/tuples/是不错的读物。