TL; DR Такая композиция является примитивной (в том смысле, что она не может быть разложена на другие функции более высокого порядка) операцией, которую не поддерживают ни Python, ни модуль tools
.Вам нужно реализовать это самостоятельно.
Чего вам не хватает (или, скорее, чего не хватает в Python и модуле tools
), так это понятия аппликативного функтора.Чтобы понять, что означает , давайте сначала рассмотрим две функции в модуле tools
:
compose
позволяет связать вместе две функции.То есть
compose(f,g) == lamba x: f(g(x))
curry
относится к частичному применению: демонстрация будет быстрее, чем объяснение:
curry(f)(x)(y) == f(x, y)
То есть curry(f)(x)
в основном совпадает с partial(f, x)
;оба принимают значение y
, чтобы вернуть значение f(x, y)
.
Кроме того, функтор в основном является способом сопоставления функции некоторому значению.Вы, несомненно, знакомы с функтором списка:
map(f, [a,b,c]) == [f(a), f(b), f(c)]
Функции являются и функторами, но вместо map
мы используем compose
.То есть отображение f
поверх g
дает compose(f, g)
.
Теперь, чтобы объединить mul
, f1
и f2
в g = lambda x: g(f1(x), f2(x))
, кажется, что оба compose
и curry
было бы полезно.
lambda x: mul(f1(x), f2(x)) == lambda x: curry(mul)(f1(x))(f2(x))
и
lambda x: mul(f1(x), f2(x)) == lambda x: compose(curry(mul), f1)(x)(f2(x))
(т. Е. curry
- это то, что позволяет нам составить функцию с двумя аргументами с другой функцией.)
Но композиция в некотором смысле строго линейная операция;ввод одной функции происходит от вывода другой.Композиция mul
и f1
создает функцию, которая ожидает аргумент , а возвращает функцию, которая ожидает тот же аргумент.Как мы можем переместить x
из «середины» любого выражения?Нам нужна какая-то загадочная функция foo
такая, что
foo(f, g) = lambda x: f(x, g(x))
, которая делает функцию, которая передает свой аргумент обоим f
и g
, одновременно передавая результатg(x)
до f
.С такой функцией foo
мы могли бы написать
lambda x: foo(compose(curry(mul), f1), f2)
и получить желаемый результат.
И это подводит нас к идее аппликативного функтора.Он обеспечивает необходимую функцию foo
def foo(f, g):
def _(x):
return f(x, g(x))
, которая объединяет понятия композиции и карри, которых у нас нет на данный момент.
Другими словами, foo
- это отличная примитивная операция;Вы не можете реализовать это с точки зрения самой композиции.