Конвейер один аргумент для нескольких функций? - PullRequest
0 голосов
/ 09 января 2019

Как вы можете передать один аргумент нескольким функциям? Например, если бы я хотел, чтобы кортеж (2,5) был передан как fst, так и snd, а затем передать результат каждого из них в качестве двух аргументов другой функции - это можно проиллюстрировать следующим гипотетическим, не рабочий, код: (2,5) |> (fst & snd) |> addUp(nr1, nr2)

Ответы [ 3 ]

0 голосов
/ 10 января 2019

Оператор конвейера полезен для реализации того, что предлагает название - конвейер , где вам нужно передать некоторые данные через серию преобразований.

Если вам нужен более сложный поток данных, вы получите намного лучшие результаты, просто используя обычный механизм для передачи данных через программу, предоставляемую F #, т.е. переменные:

let tuple = (2,5) 
let nr1 = fst tuple
let nr2 = snd tuple 
addUp nr1 nr2

Если вы работаете с кортежами, вы также можете использовать сопоставление с шаблоном:

let tuple = (2,5) 
let nr1, nr2 = tuple
addUp nr1 nr2

Вы можете изобретать комбинаторы и операторы, такие как |>, чтобы делать это без переменных, но это противоречит цели оператора конвейера, заключающейся в том, чтобы сделать код более читабельным.

0 голосов
/ 10 января 2019
(2, 5)
|> fun t -> first t, second t
||> addUp

Вторая строка передает входной кортеж обеим функциям first и second и возвращает их объединенный результат в виде нового кортежа.

Предполагается, что addUp принимает два обычных аргумента (не кортеж). Если для этого требуется кортеж, вместо этого используйте обычный оператор канала |> в последней строке.

Полный пример:

let first (a, b) = a * b
let second (a, b) = a ** b
let addUp a b = a + b

let answer =
    (2.0, 5.0)
    |> fun t -> first t, second t
    ||> addUp

// answer is 42.0
0 голосов
/ 09 января 2019

Итак, давайте начнем с лучшего примера ... и угадайте, что вы ищете

позволяет определенному добавлению вот так ... сделать явным, что он работает с 2-мя кортежами ... не карри.

let addUp : (int * int) -> int =
    fun (x,y) -> x + y

и ты хочешь идти (скажем)

let z = (2,4)|> (fun (x,y) -> 2*x,y) |> addUp

что некрасиво.

но обратите внимание, мы создаем конвейер, который преобразует 2 кортежа, а затем применяем к нему некоторую функцию.

Теперь кортеж - это «функтор» ... что означает, что когда мы получаем функцию, которая работает с типом внутри кортежа, мы можем преобразовать (поднять) его в функцию, которая работает со всем кортежем.

2 Кортеж дважды является функтором;

module TupleFst = 
    let map : ('a -> 'b) -> ('a * 'c) -> ('b * 'c) = 
        fun f (x,y) -> (f x, y)
module TupleSnd = 
    let map : ('a -> 'b) -> ('c * 'a) -> ('c * 'b) = 
        fun f (x,y) -> (x,f y)

Я определил их с помощью подписей, чтобы было понятно, что происходит.

В TupleFst мы берем функцию, которая работает с первым элементом кортежа, и «поднимаем» ее в функцию, которая работает со всем кортежем (который отображает первый элемент).

В TupleSnd мы делаем второй член кортежа.

теперь мы можем записать пример как ....

let z = (2,4)|> TupleFst.map ((*) 2) |> addUp

что лучше? ... спорно ... в этом тривиальном примере это, вероятно, делает жизнь хуже, но принцип там .... если вы посмотрите на FSharpPlus в функторах и аппликативном Theres гораздо больше на нем ... .и это может быть применено ко всем видам структур данных.

Я думаю, что пакет использует тот же синтаксис, украденный из Haskell, где, я думаю, вы можете написать выше:

let z = ((*) 2) <!> (2,4) |> addUp

но я не установил его и заставил все это работать ... так что в приведенном выше тексте может быть опечатка (ах ... я не уверен, как сказать FSharpPlus, какой функтор выбрать "map") from ... так что вышеприведенное неоднозначно и, вероятно, не компилируется ... вы, конечно, можете определить свой собственный оператор вместо "map")

let (<!>) = TupleFst.map
let (<!!>) = TupleSnd.map
let z1 = ((*) 2) <!> (2,4) |> addUp
let z2 = ((*) 2) <!!> (2,4) |> addUp

это компилирует "!" действует на 1-й элемент в кортеже "!!" на втором .... (я не уверен, что "!!" - разумное имя ... в то время как "!" идиоматично ... но что угодно)

(в данном случае это все излишне! ... другие ответы лучше ... Я думаю, что я пытался продемонстрировать, что если вы работаете в приподнятом мире (здесь кортежи), вы можете часто скрывать plumbling).

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