Я читаю Начните программировать с Haskell, чтобы понять функциональное программирование. В Уроке 10 автор обсуждает использование функционального программирования для создания простых объектов с помощью замыканий. До этого момента в книге темы включали функции высшего порядка, лямбда-функции и замыкания.
Он описывает что-то вроде:
simpleObject intAttribute= \message -> message intAttribute
simpleObject возвращает закрытие, которое в эффектах хранит атрибут intAttribute. Замыкание принимает функцию в качестве аргумента и предоставляет атрибут intAttribute в качестве параметра. Например (мой):
obj = simpleObject 5
doubleIt x = 2 * x
obj doubleIt (returns 10)
Я думаю, что до этого момента я достаточно ясен.
Затем автор описывает аксессуар, похожий на:
getAttribute y = y (\x -> x)
getAtrribute obj (returns 5)
Код работает должным образом, возвращая захваченный атрибут intAttribute. Здесь я заблудился. Как работает код getAttribute?
Ах ... это очень помогает! Я зацикливался на предпоследнем переходе. Большое спасибо!
За последнее время я второй раз сталкиваюсь с этой странной техникой (впервые на stackoverflow.com/q/53023885/4942760). Я думаю, что этот конкретный случай вообще не имеет смысла. Единственное полусмысленное использование, которое я могу придумать, - это запись закрытий для реализации гадтов бедняков (не обязательно, поскольку гадты существуют) или разрешения каких-то оо-подобных объектов / интерфейсов (но почему бы не использовать классы типов?). отличается от простого использования значения напрямую (изоморфизм - это ($id)
в одном случае и flip ($)
в другом). Для чего это должно быть полезно?
@DanRobertson Я не думаю, что у этого есть какая-то цель, но это просто упражнение по закрытию. Осознание того, что такой изоморфизм существует, также может быть еще одним упражнением. Это в основном об обучении / понимании, чем о том, чтобы быть действительно полезным само по себе (ИМО).
Мы можем оценить выражение, заменяя каждый определенный идентификатор своим собственным определением.
getAtrribute obj
= { def. getAttribute }
obj (\x -> x)
= { def. obj. }
simpleObject 5 (\x -> x)
= { def. simpleObject }
(\message -> message 5) (\x -> x)
= { beta reduction }
(\x -> x) 5
= { beta reduction }
5
Спасибо! Комментатор Алек опубликовал выше аналогичную технику, которая также прояснила код.
getAtrribute obj == obj (\x -> x) == (simpleObject 5) (\x -> x) == (\message -> message 5) (\x -> x) == (\x -> x) 5 == 5