Практика часть лямбда-абстракций - PullRequest
1 голос
/ 14 марта 2011

Я новичок в программировании на Haskell.Теперь я изучаю лямбда-функции и лямбда-абстракции.И я подумал, какова часть практики лямбда-функций.Например, у нас есть:

map(\x -> x * 2) [1,2,3,4,5]
[2,4,6,8,10]

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

Спасибо.

Ответы [ 5 ]

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

Есть два способа интерпретировать этот вопрос. Во-первых, зачем писать map (\x -> x * x), когда мы можем написать

doubleIt x = x * x
... map doubleIt ...

Ответ таков: у вас может быть следующее:

foo y zs = map (\x -> x^y) zs

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

Мы могли бы написать

foo y zs = map (powerIt y) xs
powerIt y = ?

и тогда мы обнаружим, что powerIt y = \x -> x^y! (конечно, вы можете перевести x обратно во внешнее определение, но в этом случае вы действительно захотите (хотя синтаксически Haskell не заставляет вас) написать (powerIt y) как (\x -> powerIt y x).

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

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

foo y zs = let powerIt x = x^z
           in map powerIt zs

В таком случае, подумайте о том, что на самом деле означает let. Фактически, мы можем преобразовать let в несколько лямбд следующим образом: foo ys zs = (\powerIt -> map powerIt zs) (\x -> x^y)

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

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

Инверсия перспективы состоит в том, чтобы рассматривать лямбды не как особый случай, а как общий случай, а все другие различные механизмы связывания имен - как сахар для них.

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

Не все функции используются достаточно широко, чтобы «заслужить» имя. Например, если вы используете эту функцию только один раз, для этой конкретной карты вы, вероятно, не хотите назначать ей имя, потому что вы никогда не будете использовать ее снова.

2 голосов
/ 14 марта 2011

читаемость; вы можете иметь (надуманный, но для иллюстрации сути)

map (\x -> x * 2) . anotherfunction . anotheragain . itgoesonandon $
[ a lont list ]

против

map f . anotherfunction . anotheragain . itgoesonandon $
[ a lont list ]
  where f x = x * 2

Это дело вкуса, но в первом случае вы сразу знаете, какую функцию вы отображаете, во втором вам нужно найти f в исходном коде, и это может быть в нескольких строках.

Кстати, я бы написал map (*2) .... в любом случае

Другой пример - десагарадная монадическая запись.

Например,

do a <- action1
   b <- action2
   action3
   c <- action4 a b
   action5 c

становится:

action1 >>= \a -> action2 >>= \b -> action3 >> action4 a b >>= \c -> action5 c

против

action1 >>= a2
  where a2 a = action2 >>= a3
           where a3 b = action3 >> action4 a b >>= a4
                   where a4 c = action5 c

(в этом коде может быть ошибка, но я бы никогда так не написал)

2 голосов
/ 14 марта 2011

Вы часто сталкиваетесь с ситуацией, когда вам нужна довольно специализированная функция. Он используется в этой части вашего программного обеспечения и только там. Поэтому не имеет никакого смысла давать ему конкретное имя.

0 голосов
/ 14 марта 2011

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

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

Как было отмечено выше комментатором, Функциональное программирование имеет свои корни в лямбда-исчислении. Я могу только посоветовать вам прочитать соответствующие записи в Википедии, там есть очень интересная информация; -).

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