Подтвердить что ты не робот

Хорошее объяснение "Комбинаторов" (для не математиков)

Кто-нибудь получил хорошее объяснение "комбинаторов" (Y-комбинаторы и т.д., а не компания)

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

(Обратите внимание, что я говорю об этих вещах: http://en.wikipedia.org/wiki/Y_combinator)

4b9b3361

Ответ 1

Если вы глубоко вникаете в теорию, вы можете оценить Y combinator как опрятный трюк с функциями, как монады.

Монады позволяют вам цепочки действий, Y combinator позволяет вам определить саморекурсивные функции.

Python имеет встроенную поддержку саморекурсивных функций, поэтому вы могут определять их без Y:

> def fun():
>  print "bla"
>  fun()

> fun()
bla
bla
bla
...

fun доступен внутри fun, поэтому мы можем легко называть его.

Но что, если Python были разными, а fun недоступны внутри fun?

> def fun():
>   print "bla"
>   # what to do here? (cannot call fun!)

Решение состоит в том, чтобы передать fun как аргумент fun:

> def fun(arg): # fun receives itself as argument
>   print "bla"
>   arg(arg) # to recur, fun calls itself, and passes itself along

И Y делает это возможным:

> def Y(f):
>   f(f)

> Y(fun)
bla
bla
bla
...

Все это он вызывает функцию с собой как аргумент.

(я не знаю, правильно ли это определение Y на 100%, но я думаю, что это общая идея.)

Ответ 2

Реджинальд Брейтуэйт (он же Раганвальд) пишет в своем новом блоге великолепную серию о комбинаторах в Ruby, homoiconic.

Пока он (насколько мне известно) не смотрит на сам Y-combinator, он смотрит на другие комбинаторы, например:

и несколько сообщений о том, как вы можете использовать их.

Ответ 3

Цитата Википедия:

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

Что это значит? Это означает, что комбинатор является функцией (выход определяется исключительно его входом), вход которого включает функцию в качестве аргумента.

Как выглядят такие функции и для чего они используются? Вот несколько примеров:

(f o g)(x) = f(g(x))

Здесь o - комбинатор, который принимает 2 функции, f и g, и возвращает в качестве результата свою функцию, состав f с g, а именно f o g.

Комбинаторы могут использоваться для скрытия логики. Скажем, у нас есть тип данных NumberUndefined, где NumberUndefined может принимать числовое значение Num x или значение Undefined, где x a является Number. Теперь мы хотим построить сложение, вычитание, умножение и деление для этого нового числового типа. Семантика такая же, как и для Number, за исключением того, что если Undefined является входом, вывод также должен быть Undefined, а при делении на число 0 вывод также Undefined.

Можно написать утомительный код, как показано ниже:

Undefined +' num = Undefined
num +' Undefined = Undefined
(Num x) +' (Num y) = Num (x + y)

Undefined -' num = Undefined
num -' Undefined = Undefined
(Num x) -' (Num y) = Num (x - y)

Undefined *' num = Undefined
num *' Undefined = Undefined
(Num x) *' (Num y) = Num (x * y)

Undefined /' num = Undefined
num /' Undefined = Undefined
(Num x) /' (Num y) = if y == 0 then Undefined else Num (x / y)

Обратите внимание, что все имеют одинаковую логику относительно входных значений Undefined. Только деление делает немного больше. Решение состоит в том, чтобы извлечь логику, сделав ее комбинатором.

comb (~) Undefined num = Undefined
comb (~) num Undefined = Undefined
comb (~) (Num x) (Num y) = Num (x ~ y)

x +' y = comb (+) x y
x -' y = comb (-) x y
x *' y = comb (*) x y
x /' y = if y == Num 0 then Undefined else comb (/) x y

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

Ответ 4

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

Используя F #, это мое понимание комбинаторов:

let sum a  b = a + b;; //sum function (lambda)

В приведенной выше сумме сумма представляет собой комбинатор, поскольку оба a и b привязаны к параметрам функции.

let sum3 a b c = sum((sum a b) c);;

Вышеуказанная функция не является комбинатором, так как использует sum, которая не является связанной переменной (т.е. она не исходит ни от одного из параметров).

Мы можем сделать sum3 комбинатором, просто передав функцию суммы как один из параметров:

let sum3 a b c sumFunc = sumFunc((sumFunc a b) c);;

Этот способ sumFunc связан, и, следовательно, вся функция является комбинатором.

Итак, это мое понимание комбинаторов. С другой стороны, их значение все еще ускользает от меня. Как отмечали другие, комбинаторы с фиксированными точками позволяют выразить рекурсивную функцию без рекурсии explicit. То есть вместо вызова функции recusrsive вызывает lambda, которая передается как один из аргументов.

Вот один из наиболее понятных разборчиков комбинаторов, который я нашел:

http://mvanier.livejournal.com/2897.html

Ответ 6

Это хорошая статья:

http://www.dreamsongs.com/NewFiles/WhyOfY.pdf

Примеры кода приведены в схеме, но с ними не должно быть трудно следовать.

Ответ 7

Я довольно коротко отношусь к теории, но я могу привести пример, который заставляет мое воображение вздыматься, что может быть полезно для вас. Самый простой интересный комбинатор, вероятно, "тест".

Надеюсь, вы знаете Python

tru = lambda x,y: x
fls = lambda x,y: y 

test = lambda l,m,n: l(m,n)

Использование:

>>> test(tru,"goto loop","break")
'goto loop'
>>> test(fls,"goto loop","break")
'break'

test оценивает второй аргумент, если первый аргумент истинен, в противном случае третий.

>>> x = tru
>>> test(x,"goto loop","break")
'goto loop'

Целые системы могут быть созданы из нескольких основных комбинаторов.

(Этот пример более или менее скопирован из типов и языков программирования Бенджамином С. Пирсом)

Ответ 8

Вскоре Y combinator является функцией более высокого порядка, которая используется для реализации рекурсии на лямбда-выражениях (анонимные функции). Проверьте статью Как добиться успеха в рекурсии без реальной рекурсии Майком Ванье - это одно из лучших практических объяснений этого вопроса, которое я видел.

Также сканируйте архивы SO: