Превратить список Результата в Результат списка внутри выражения вычисления? - PullRequest
0 голосов
/ 11 июня 2018

У меня есть Result<'T, 'E> list, который я хотел бы превратить в один Result<'T list, 'E>, следуя этим правилам:

  • Если любой Result равен Error, то результат должен бытьError
  • Если результат Error, то он должен быть первым Error в списке
  • Если каждый результат OK, то результат должен быть Ok и порядок списка должен быть сохранен

Итак, я попробовал и реализовал это следующим образом:

let all xs = 
  let folder = fun state next -> 
    match (state, next) with 
    | (Result.Ok ys, Result.Ok y) -> ys |> List.append [ y ] |> Result.Ok
    | (Result.Error e, _) -> Result.Error e 
    | (_, Result.Error e) -> Result.Error e 
  Seq.fold folder (Result.Ok []) xs

Однако, похоже, что-то, что уже могло быть реализовано встандартная библиотека.Есть это?

Во-вторых, у меня есть вычислительное выражение для Result, например:

type ResultBuilder () = 
  member this.Bind(x, f) = 
    match x with 
    | Result.Ok o -> f o
    | Result.Error e -> Result.Error e
  member this.Return(value) = Result.Ok value
  member this.ReturnFrom(value) = value

let result = new ResultBuilder()

Я могу использовать all внутри result { ... }, но возможна ли дальнейшая интеграция?Например, путем реализации ResultBuilder.For?

1 Ответ

0 голосов
/ 11 июня 2018

У вас есть Result<'a, 'e> list и вы хотите Result<'a list, 'e>.Это похоже на функцию sequence, описанную в https://fsharpforfunandprofit.com/posts/elevated-world-4/ (которая не имеет ничего общего с seq s, несмотря на то, как звучит название).Быстрая проверка https://github.com/fsharp/fsharp/blob/master/src/fsharp/FSharp.Core/result.fs показывает, что эта функция не была реализована в стандартной библиотеке FSharp.Core, поэтому вам нужно реализовать ее самостоятельно.

Кстати, если вы этого не сделалиЯ уже читал серию Скотта Влашина «Поднятый мир», я не рекомендую начинать со средней статьи, на которую я ссылаюсь.Вместо этого начните с этой статьи , поскольку она формирует базовые знания, которые вам необходимы, чтобы понять, что делают функции "traverse" и "sequence".Тогда вы узнаете общую схему реализации одной из этих функций.

Что касается вашего второго вопроса, не могли бы вы предоставить несколько дополнительных деталей?Например, какое поведение вы хотите от ResultBuilder.For?Обычное поведение, ожидаемое от выражения for, состоит в том, чтобы взять Result<'a, 'e> list (или seq или массив) и запустить внутренний блок один раз для каждого Result<'a, 'e>, который находится в списке, seq или массиве.Если вы попытаетесь использовать здесь свою функцию all, у вас будет несоответствие типов между Result<'a, 'e> (это то, что F # будет ожидать от метода .For CE) и Result<'a list, 'e>, что и ваше allметод возвращается.Что конкретно вы хотите, чтобы ваш метод ResultBuilder.For сделать?

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