Чего мне не хватает: возможна ли композиция с несколькими аргументами? - PullRequest
10 голосов
/ 27 марта 2011

Я понимаю основы композиции функций в F #, как, например, описано здесь .

Может быть, я чего-то упускаю.* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * "* 100 *" * * * * * * "* Это только то, что я хотел бы сделать: * 100" * * 1009 "

let add a b = a + b
let double c = 2*c
let addAndDouble = add >> double   // bad!

Но даже если вывод add относится к типу, необходимому для ввода double, он отклоняется.

Я знаю, что могу переписать add с однимАргумент кортежа:

let add (a,b) = a + b

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

let inline (>>+) f g x y = g (f x y)
let doubleAdd = add >>+ double

Но это кажется глупым!Есть ли лучший способ, который я пропустил?

Ответы [ 3 ]

12 голосов
/ 27 марта 2011

То, что вы хотите, не является абсолютно необоснованным, но не было бы никакого способа указать тип обобщенного оператора композиции в системе типов F #. То есть, нет хорошего способа объединить

(>>) : ('a -> 'b) -> ('b -> 'c) -> 'a -> 'c

и

(>>+) : ('a -> 'b -> 'c) -> ('c -> 'd) -> 'a -> 'b -> 'd

(не говоря уже о бесконечном множестве версий высшей арности). Поэтому у вас нет альтернативы, кроме как определить свои собственные дополнительные операторы. На практике я часто нахожу код, написанный в «остроконечном» стиле let f x y = add x y |> double, более читабельным, чем бессмысленный / «бессмысленный» let f = add (>>+) double в любом случае.

4 голосов
/ 27 марта 2011

Посмотрите на типы >> и <<, которые вы разместили выше. например:

> (>>);;
val it : (('a -> 'b) -> ('b -> 'c) -> 'a -> 'c) = <fun:it@214-13>

Он принимает две функции и значение ('a) и возвращает другое значение. Вам нужно что-то, что принимает две функции и 2 значения. Следовательно, и >>, и << не имеют правильной сигнатуры типа.

Ваша реализация вовсе не глупая. Просто ваше требование не выходит из коробки в библиотеках F #. Будьте благодарны, что у вас есть язык, который позволяет вам определять свои собственные операторы следующим образом:)

3 голосов
/ 21 апреля 2011

Как насчет того, чтобы пропустить стек аргументов?

let add = function x :: y :: t -> x + y :: t
let double = function x :: t -> 2 * x :: t

Затем вы можете составить произвольные функции арности:

let doubleAdd = add >> double

И это работает:

> doubleAdd [7; 14]
42

(см. Также F # Композиция функций с несколькими входными параметрами )

...