2010-07-10 7 views
5

Я новичок в F # и я недавно обнаружил оператор функции композиции >>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 ожидает кортеж.

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

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

+4

Я не совсем понимаю вашу точку с помощью 'AddNum >> MulNums', выход AddNums является одним числом, таким образом, не допустимый формат вход MulNums, что означает, две функции просто не являются составными. –

ответ

8

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

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

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

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) 

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

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' 
+0

Спасибо Томасу, это объясняет это очень хорошо! –

+0

@ Томас: Боюсь, вы использовали неправильного оператора со стрелками. Должно быть (***);) – Gustavo

+0

let (***) f g (a, b) = (f a, g b) let (&&&) f g a = (f a, g a) – ben

1

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

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

let Add1 x = AddNums(x, 1) 
let Mul2 x = MulNums(x, 2) 
let FuncComp = Add1 >> Mul2 

При запуске:

FuncComp (1) ;;

вал это: INT = 4

+0

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

1

Еще один вариант сделать Пакетирование> функции стека много как калькулятор 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)

Смежные вопросы