Более эффективный вариант того же, что показан ниже.Это означает, что теперь это по сути копия ответа @ GeneBelitski.
let run input calc =
let inputList = Seq.toList input
let rec subrun inp acc =
match inp with
| [] -> (acc, "Done")
| (x :: xs) ->
let res = calc x
match res with
| Some(y) -> subrun xs (acc + y)
| None -> (acc, "Error")
subrun inputList 0
Обратите внимание, что эта функция ниже ОЧЕНЬ медленная, вероятно, потому что она использует Seq.tail (я думал, что это будет то же самоекак List.tail).Я оставляю это для потомков.
Самый простой способ, которым я могу придумать для выполнения этого в F #, это использовать хвостовую рекурсивную функцию.Что-то вроде
let run input calc =
let rec subrun inp acc =
if Seq.isEmpty inp then
(acc, "Done")
else
let res = calc (Seq.head inp)
match res with
| Some(x) -> subrun (Seq.tail inp) (acc + x)
| None -> (acc, "Error")
subrun input 0
Я не уверен на 100%, насколько это будет эффективно.По моему опыту, иногда по какой-то причине мои собственные хвостовые рекурсивные функции кажутся значительно медленнее, чем использование встроенных функций высшего порядка.Это должно, по крайней мере, привести вас к правильному результату.
Нижеследующее, хотя и не отвечает на реальный вопрос, оставлено только на тот случай, если оно кому-нибудь пригодится.
Типичный способ справиться с этим - заставить функцию calc возвращать тип Option или Result, например,
let calc1 x = if x = 3 then None else Some(x*2)
, а затем сопоставить это с вашим вводом.После этого вы можете довольно легко сделать что-то вроде
|> Seq.exists Option.isNone
, чтобы проверить, есть ли Nones в результирующем seq (вы можете направить его на нет, если хотите получить противоположный результат).
Если вам просто нужно исключить Nones из списка, вы можете использовать
Seq.choose id
, который удалит все None, оставив параметры без изменений.
Для суммирования списка, предполагая, что вы использоваливыберите остаться только с некоторыми, тогда вы можете сделать
Seq.sumBy Option.get