Реализация take с F # путем перевода эквивалента ML - PullRequest
3 голосов
/ 06 июня 2011

Я бы хотел перевести этот код 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 #?

Ответы [ 2 ]

9 голосов
/ 06 июня 2011

Просто, чтобы добавить несколько комментариев, я думаю, что лучший способ написать функцию на 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
    
7 голосов
/ 06 июня 2011

Поскольку 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)
...