#f#
#f#
Вопрос:
Мне нравится использовать ROP, когда мне приходится иметь дело с вводом-выводом / разбором строк /…
Однако предположим, что у меня есть функция, принимающая 2 параметра. Как вы можете сделать чистое / читаемое частичное приложение, когда ваши 2 параметра уже являются результатом<‘a,’b> (необязательно те же ‘a, ‘b)?
На данный момент, что я делаю, так это то, что я использую tuple для передачи параметров и использую приведенную ниже функцию для получения результата из кортежа, чтобы затем я мог связать свою функцию с этим «параметром кортежа».
/// Transform a tuple of Result in a Result of tuple
let tupleAllResult x =
match (fst x, snd x) with
| Result.Ok a, Result.Ok b -> (a,b) |> Result.Ok
| Result.Ok a, Result.Error b -> b |> Result.Error
| Result.Error a, _ -> a |> Result.Error
let f (a: 'T, b: 'U) = // something
(A, B) |> tupleAllResult
|> (Result.bind f)
Есть хорошая идея?
Вот то, что я написал, которое работает, но, возможно, не самое элегантное
let resultFunc (f: Result<('a -> Result<'b, 'c>), 'd>) a =
match f with
| Result.Ok g -> (g a) |> Result.Ok |> Result.flatten
| Result.Error e -> e |> Result.Error |> Result.flatten
Ответ №1:
Я не вижу в вашем примере частичного применения концепции, связанной с обработкой и передачей аргументов — вот почему я предполагаю, что вы придерживаетесь монадического apply
подхода, поскольку вы хотите преобразовать функцию, обернутую в Result
значение, в функцию, которая принимает Result
и возвращает другое Result
.
let (.>>.) aR bR = // This is "tupleAllResult" under a different name
match aR, bR with
| Ok a, Ok b -> Ok(a, b)
| Error e, _ | _, Error e -> Error e
// val ( .>>. ) : aR:Result<'a,'b> -> bR:Result<'c,'b> -> Result<('a * 'c),'b>
let (<*>) fR xR = // This is another name for "apply"
(fR .>>. xR) |> Result.map (fun (f, x) -> f x)
// val ( <*> ) : fR:Result<('a -> 'b),'c> -> xR:Result<'a,'c> -> Result<'b,'c>
Разница с тем, что у вас есть в вашем вопросе, заключается map
вместо bind
в последней строке.
Теперь вы можете начать внедрять lift
функции в Result
мир:
let lift2 f xR yR =
Ok f <*> xR <*> yR
// val lift2 :
// f:('a -> 'b -> 'c) -> xR:Result<'a,'d> -> yR:Result<'b,'d> -> Result<'c,'d>
let res : Result<_,unit> = lift2 ( ) (Ok 1) (Ok 2)
// val res : Result<int,unit> = Ok 3
Комментарии:
1. Спасибо! действительно, я сильно запутался, теперь все яснее