Композиция F # Function с несколькими входными параметрами - PullRequest
6 голосов
/ 10 июля 2010

Я новичок в F #, и недавно я обнаружил оператор композиции функций >>

Я понимаю основной принцип, так что что-то подобное возможно ...

let Add1ToNum x = x +1
let Mul2ToNum y = y * 2
let FuncComp = Add1ToNum >> Mul2ToNum

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

let AddNums (x,y) = x+y
let MulNums (x,y) = x*y
let FuncComp = Add1 >> Mul2

Что, очевидно, не 'это не работает, потому что AddNums возвращает int, а MulNums ожидает кортеж.

Существует ли какая-либо форма синтаксиса, которая позволяет мне выполнить это, или, если я хочу использовать составление функций, мне всегда нужно выполнять какую-то промежуточную функцию для преобразования значений?

Любые предложения по этому вопросу будут высоко оценены.

Ответы [ 3 ]

8 голосов
/ 10 июля 2010

Как указали Инь и codekaizen, вы не можете объединить две функции, чтобы создать функцию, которая передает входные данные первой, а затем передает выходные данные этого вызова второй функции (то есть, используя оператор th >>).).Используя диаграмму, вы не можете сделать:

     +---------+    +---------+
 --->| AddNums |--->| MulNums |--->
     +---------+    +---------+

Один из вариантов - изменить функцию и указать один из параметров, чтобы можно было составлять функции.Пример codekaizen использует это и может также быть написан так (если вы используете каррирование вместо параметров с кортежем):

let AddNums x y = x + y  
let MulNums x y = x * y  
let FuncComp = (AddNums 1) >> (MulNums 2)

Другой вариант для составления функций - создать функцию, которая принимает несколько входных данных, передаетдва числа для первой функции, а затем вызывает вторую функцию с результатом и другим числом из исходных входов.Используя диаграмму:

 -----------------\
 --->+---------+   \+---------+
 --->| AddNums |--->| MulNums |--->
     +---------+    +---------+

Если вам нужно что-то подобное, тогда лучшим вариантом будет написать это напрямую, потому что это, вероятно, не будет часто повторяющимся шаблоном.Непосредственно, это легко (с использованием варианта с карри):

let AddNums x y = x + y  
let MulNums x y = x * y  
let FuncComp x y z = AddNums z y |> (MulNums z)

Если вы хотите написать что-то подобное в более общем плане (или просто для любопытства), вы можете написать что-то вроде этого (используя кортежную версиюфункции на этот раз).Оператор &&& вдохновлен Стрелками :

let AddNums (x,y) = x + y 
let MulNums (x,y) = x * y  

let (&&&) f g (a, b) = (f a, g b)
let FuncComp = (AddNums &&& id) >> MulNums

// First two numbers are added, result is multiplied by the third one
FuncComp ((9, 12), 2) // Gives '42'
1 голос
/ 21 апреля 2011

Еще один вариант - сделать функции стека-> стека очень похожими на калькулятор RPN.Например:

let bin f = function a :: b :: t -> f b a :: t
let add = bin (+)
let mul = bin (*)

И, возможно, функция для вставки литералов в стек:

let lit n t = n :: t

Тогда это чистая композиция:

> (lit 9 >> lit 12 >> add >> lit 2 >> mul) []
42

Вы можете даже добавитьфункции перемешивания в стеке:

let drop = function _ :: t -> t
let dup  = function x :: t -> x :: x :: t
let swap = function x :: y :: t -> y :: x :: t

И такие вещи:

let square = dup >> mul
let cube = dup >> dup >> mul >> mul
let negate = lit -1 >> mul

Просто эксперимент в безумии!

(См. также http://blogs.msdn.com/b/ashleyf/archive/2011/04/21/programming-is-pointless.aspx)

1 голос
/ 10 июля 2010

Как указывает Инь, ваши типы не совпадают при создании.AddNums и MulNums относятся к типу int * int -> int, поэтому вы не можете ожидать подключения выхода одного к входу другого.

Я отмечаю, что ваша последняя строка let FuncComp = Add1 >> Mul2которая может быть опечаткой, но дает представление о том, как вы можете «связать» функции, которые принимают кортежи, так что они составляют:) ;;

val it: int = 4

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