Оценить список значений выражений вычислений - PullRequest
0 голосов
/ 12 ноября 2018

Какой хороший способ вычислить список значений выражений вычислений в соответствующий список значений?

Допустим, мой тип выражения для вычисления M<a>, тогда мне интересно, как лучше написать функцию:

mysequence : list<M<'a>> -> M<list<'a>>

Я мог бы написать это рекурсивно:

let rec mysequence = function
    | [] -> builder { return [] }
    | (x::xs) -> builder { let! y = x
                           let! ys = mysequence xs
                           return (y::ys)
                         }

Есть ли более лаконичный способ?

1 Ответ

0 голосов
/ 12 ноября 2018

Вы могли бы сделать это немного короче, используя 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 }

Но кроме аккумулятора и некоторых незначительных синтаксических различий, он почти такой же, как ваш!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...