Вы могли бы сделать это немного короче, используя List.fold
, и даже короче, если бы вы ввели пару вспомогательных комбинаторов, таких как функция lift2
следующего типа:
lift2 : ('a -> 'b -> 'c) -> M<'a> -> M<'b> -> M<'c>
Это то, что вы можете легко определить с помощью нотации builder { .. }
, и оно позволяет вам превращать функции, работающие с обычными значениями, в функции, работающие с переносимыми значениями. Затем вы можете поднять операцию обработки списка и использовать ее со сгибом. Это сделает код короче (если вы проигнорируете всех помощников, которые нужно написать), но также сделает его довольно уродливым и неясным.
Если бы я писал это, я бы подошел к чему-то очень близкому к вашей версии. Я предпочитаю хранить все тело в builder { .. }
вместо function
, и я бы также использовал параметр аккумулятора, поэтому я бы написал:
let rec mysequence acc input = builder {
match input with
| [] -> return List.rev acc
| x::xs ->
let! y = x
return! mysequence (y::acc) xs }
Но кроме аккумулятора и некоторых незначительных синтаксических различий, он почти такой же, как ваш!