Является ли "a -> b -> (a -> b -> c) -> c" для применения двух параметров стандартной функциональной концепцией? - PullRequest
0 голосов
/ 03 мая 2018

Я столкнулся с необходимостью использования функции с подписью 'a -> 'b -> ('a -> 'b -> 'c) -> 'c для применения двух аргументов при конвейере:

let apply2 x y f =
  f x y

Мне это нужно, потому что я использую функцию

myFun : MyType -> TypeA -> TypeB -> ResultType

и я использую его в другой функции, подобной этой:

let useCase someValue (valueA: TypeA) (valueB: TypeB) =
  someValue
  |> ...
  |> toMyType
  |> myFun
  |> apply2 valueA valueB

apply2 отвечает всем требованиям, но я не могу избавиться от ощущения, что могу использовать встроенную функцию или оператор или что мне не хватает более фундаментального способа сделать это (кроме лямбд, которые, по-моему, хуже читаются в этот случай). Обратите внимание, что я не могу легко изменить порядок параметров myFun (это Giraffe HttpHandler, поэтому последние два параметра должны быть HttpFunc и HttpContext, обозначенные TypeA и TypeB выше) .

Является ли функция apply2 с сигнатурой, которую я описал, приемлемой для функционального программирования, или я упускаю что-то очевидное? Если это общеизвестная концепция, имеет ли она лучшее название?

Ответы [ 3 ]

0 голосов
/ 03 мая 2018

Вы можете использовать маленький трюк здесь:

let useCase someValue ((valueA, valueB) as tuple) =
    someValue
    |>  ...
    |>  toMyType
    |>  myFun
    <|| tuple

или просто

let useCase someValue tuple =
    ...
0 голосов
/ 03 мая 2018

В вашем трубопроводе вы можете заменить:

 |> apply2 valueA valueB

с

 |> (||>) (valueA, valueA)

То есть ||> - это то же самое, что и ваша apply2 функция, но с аргументами с кортежами.

0 голосов
/ 03 мая 2018

На мой взгляд, код будет намного понятнее, если связать промежуточное значение с let.

let useCase someValue (valueA: TypeA) (valueB: TypeB) =
    let myValue =
        someValue
        |> ...
        |> toMyType
    myFun myValue valueA valueB

Вы также можете использовать обратные трубы следующим образом

let useCase someValue (valueA: TypeA) (valueB: TypeB) =
    someValue
    |> ...
    |> toMyType
    |> myFun <| valueA <| valueB
...