3

我想将此 ML 代码翻译成 F#。

fun take ([], i) = []
  | take (x::xs, i) = if i > 0 then x::take(xs, i-1) 
                                else [];

我试过这个

let rec take n i =
  match n,i with 
    | [], i -> []
    | x::xs, i -> if i > 0 then x::take(xs, i-1)
                           else [];

let val = take [1;2;3;4] 3

和这个

let rec take input =
  match input with 
    | ([], i) -> []
    | (x::xs, i) -> if i > 0 then x::take(xs, i-1)
                           else [];

let val = take ([1;2;3;4] 3)

但是他们都给了我一个错误take.fs(7,5): error FS0010: Unexpected keyword 'val' in binding。F# 代码有什么问题?

4

2 回答 2

9

只是添加一些评论,我认为在 F# 中编写函数的最好方法是使用:

let rec take i n=  
  match n, i with
  | [], i -> []
  | _, i when i <= 0 -> []
  | x::xs, i -> x::(take (i-1) xs)

我做了两个改变:

  • 使用模式匹配来测试是否i <= 0(与 做同样的事情if,但看起来更好一点)
  • 颠倒参数的顺序,以便最重要的参数(输入列表)是最后一个。这使得可以通过流水线操作符很好地使用该函数:

    [1;2;3;4] |> take 3
    
于 2011-06-05T22:06:22.520 回答
7

由于val是 F# 中的保留关键字,因此不能将其用作值。您的第一个版本take是错误的,因为take(xs, i-1)(元组形式)的类型与take n i(咖喱形式)的类型不同。这有效:

let rec take n i =
  match n, i with 
    | [], i -> []
    | x::xs, i -> if i > 0 then x::(take xs (i-1)) else []

let value = take [1;2;3;4] 3

第二个版本在调用函数的方式上有一个错误。它可以固定如下:

let rec take input =
  match input with 
    | [], i -> []
    | x::xs, i -> if i > 0 then x::take(xs, i-1) else []

let value = take ([1;2;3;4], 3) // Notice ',' as tuple delimiter

或者你可以写更接近你的 ML 函数:

let rec take = function 
    | [], i -> []
    | x::xs, i -> if i > 0 then x::take(xs, i-1) else []

let value = take ([1;2;3;4], 3)
于 2011-06-05T21:46:31.867 回答