F# функция в качестве аргумента в функции соответствия
Я сделал функцию, которая принимает список и список списков и возвращает новый список списков.
let rec calculator list SS =
match (List.item(0) SS) with
|[] -> []
|_ -> match (validate list (List.item(0) SS)) with
|(validate theCode list) -> List.append [(List.item(0) SS)] (calculator list (SS.[1..]))
|_ -> (calculator list (SS.[1..]))
validate - это функция, которая возвращает два кортежа. пример (1,1)
список это список из четырех целых
SS - список списков с четырьмя целыми числами
theCode представляет собой список из четырех целых
я получаю сообщение об ошибке "Дискриминатор шаблона 'validate' не определен".
Возможно, это глупый вопрос, но тем не менее я не знаю ответа на него.
Разрешено ли использовать функцию в качестве аргумента в выражении соответствия. Или здесь происходит что-то совершенно другое?
Насколько мне известно, две функции проверки будут возвращать два кортежа и поэтому должны быть в состоянии соответствовать этому.
2 ответа
Если ваш вопрос заключается в том, как заставить это скомпилировать, то вам нужно лишь небольшое изменение - вызов функции не является шаблоном, поэтому вам нужно привязать значение и использовать when
охранник:
let rec calculator list SS =
match (List.item(0) SS) with
| [] -> []
| _ ->
match (validate list (List.item(0) SS)) with
// vvvvvvvvvv
| x when x = (validate theCode list) ->
List.append [(List.item(0) SS)] (calculator list (SS.[1..]))
| _ -> (calculator list (SS.[1..]))
Однако, если ваш вопрос действительно " какой метод предпочтителен ", то, хотя это слишком субъективно для этого сайта (IMO), я передам это как вариант, который я считаю идеально читаемым для этой логики:
let rec calculator list (h::t) =
if List.isEmpty h then h
elif validate list h = validate theCode list then h::(calculator list t)
else calculator list t
(Это предполагает, что SS
это список F#, а не System.Collections.Generic.List
.)
На самом деле это не ответ на вопрос о том, как реализовать when
охранник, так как @ildjarn ответил, что для вас.
Я думаю, что на самом деле вы бы лучше обслуживали библиотечную функцию. Похоже, вы пытаетесь отфильтровать элементы, которые не проходят проверку, но также остановиться на первом пустом элементе. Если вы можете гарантировать, что вы определенно хотите пройтись по каждому элементу SS
Вы могли бы просто сделать
let calculator list = List.filter (fun s -> validate list s = validate theCode list)
Если вы должны остановиться на пустом элементе, вы можете определить функцию, которая сокращает список в первом пустом элементе, что-то вроде
let upToElement element list =
let rec loop acc = function
| [] -> List.rev acc
| h :: t when h = element -> List.rev acc
| h :: t -> loop (h :: acc) t
loop [] list
тогда вы можете сделать
let calculator list =
upToElement [] >> List.filter (fun s -> validate list s = validate theCode list)