Здравствуйте, Курилка, Вы писали:
К>Дума, стоит упомянуть сабжевую статью Конала Эллиота, тем более описываемые там утверждения уже проскакивали тут на форуме.
попытался прочитать но там много.
можно в двух словах что он хотел сказать?
Здравствуйте, cvetkov, Вы писали:
C>Здравствуйте, Курилка, Вы писали:
К>>Дума, стоит упомянуть сабжевую статью Конала Эллиота, тем более описываемые там утверждения уже проскакивали тут на форуме.
C>попытался прочитать но там много. C>можно в двух словах что он хотел сказать?
Идея, видимо пришла из ООПшного "всё есть объект", но это скорее рационализация, чем истинное утверждение ("контрпример" — если 3, число, — константная функция, то что же возвращает эта функция)
Здравствуйте, Курилка, Вы писали:
К>Здравствуйте, cvetkov, Вы писали:
C>>Здравствуйте, Курилка, Вы писали:
К>>>Дума, стоит упомянуть сабжевую статью Конала Эллиота, тем более описываемые там утверждения уже проскакивали тут на форуме.
C>>попытался прочитать но там много. C>>можно в двух словах что он хотел сказать?
К>Идея, видимо пришла из ООПшного "всё есть объект", но это скорее рационализация, чем истинное утверждение ("контрпример" — если 3, число, — константная функция, то что же возвращает эта функция)
Она возвращает константную функцию — число 3. Те возвращает сама себя. Какие проблемы?
Здравствуйте, gandjustas, Вы писали:
G>Здравствуйте, Курилка, Вы писали:
К>>Идея, видимо пришла из ООПшного "всё есть объект", но это скорее рационализация, чем истинное утверждение ("контрпример" — если 3, число, — константная функция, то что же возвращает эта функция)
G>Она возвращает константную функцию — число 3. Те возвращает сама себя. Какие проблемы?
Здравствуйте, gandjustas, Вы писали:
G>Здравствуйте, Курилка, Вы писали:
К>>Здравствуйте, cvetkov, Вы писали:
C>>>Здравствуйте, Курилка, Вы писали:
К>>>>Дума, стоит упомянуть сабжевую статью Конала Эллиота, тем более описываемые там утверждения уже проскакивали тут на форуме.
C>>>попытался прочитать но там много. C>>>можно в двух словах что он хотел сказать?
К>>Идея, видимо пришла из ООПшного "всё есть объект", но это скорее рационализация, чем истинное утверждение ("контрпример" — если 3, число, — константная функция, то что же возвращает эта функция)
G>Она возвращает константную функцию — число 3. Те возвращает сама себя. Какие проблемы?
с точки зрения хаскеля так думать можно. это конечно не обязательно, но если не хочется отказыватся от "все есть функция" то придется.
но если бы в хаскеле использовались бы числа черча, то это было бы не так.
Здравствуйте, Курилка, Вы писали:
К>Здравствуйте, gandjustas, Вы писали:
G>>Здравствуйте, Курилка, Вы писали:
К>>>Идея, видимо пришла из ООПшного "всё есть объект", но это скорее рационализация, чем истинное утверждение ("контрпример" — если 3, число, — константная функция, то что же возвращает эта функция)
G>>Она возвращает константную функцию — число 3. Те возвращает сама себя. Какие проблемы?
К>Тип покажи
У тройки тип Int, можно считать что это функция с нулем аргументов, которая возвращает себя, а может и ниче не возвращает, так как в типизированной лямбде для функций с нулем аргументов аппликация неприменима.
Здравствуйте, gandjustas, Вы писали:
G>Она возвращает константную функцию — число 3. Те возвращает сама себя. Какие проблемы?
Функция — это отображение чего-то на что-то.
"на что-то" у нас есть: на себя.
Осталось позаботиться об "отображении" и "чего-то".
В роли "чего-то" пусть выступает любое пустое значение.
3 = 3() = 3()() = 3()()() и т.д.
"Отображение" — вызов функции. Есть ли язык, в котором вызов не был бы встроенным действием?
Последнее, что нам нужно — конструктор, превращающий обычное значение в функцию-самограйку.
На нетипизированных языках это провернуть несложно
def constfunc(x) :
def f() :
return f
# или, для пущей уникальности - свяжем xreturn constfunc(x)
return f
Этюд для любителей писанины: выразить оба решения через лямбда-исчисление, с помощью операции Ы (Y).
На типизированных, кстати, тоже. Если у нас есть возможность ad-hoc перегрузить вызов.
Не скажу за хаскелл, насколько там можно наколдовать с $ напрямую.
В С++ же это элементарно
template<class T>
struct constfunc
{
T original; // вдруг кому-то захочется таки посмотреть
constfunc() {}
constfunc(const T& src) : original(src) {}
typedef constfunc result_type; // для совместимости с механизмом вывода boost::bind
result_type operator() () const { return *this; }
};
Единственный вопрос: А НАФИГА?
У объектов есть всякие полезные свойства. Мы можем использовать их идентичность (сравнивать адреса); обращаться к их данным и методам.
Что мы можем сделать с функцией, кроме как применить её к какому-то значению? Но, поскольку константа (по нашему определению) возвращает себя же...
Выход один: эта функция должна реагировать на пароль
def constfunc(x) :
def f(p = None) :
if p is True :
return x
else :
return f
return f
three = constfunc(3)
print three # function<.....>print three(1)(2)(3) # function<.....>print three(1)(2)(3)(False)(True) # 3
В этом прослеживается аналогия с числами Чёрча — когда число является комбинатором. Но аналогия очень зыбкая.
Здравствуйте, gandjustas, Вы писали:
G>У тройки тип Int, можно считать что это функция с нулем аргументов, которая возвращает себя, а может и ниче не возвращает, так как в типизированной лямбде для функций с нулем аргументов аппликация неприменима.
G>Это только вопрос идеологии.
Что такое функция с нулём аргументов? Она применяется к юниту (нуль-арному кортежу) или вообще не применяется?
Если не применяется — какая же это функция?
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, gandjustas, Вы писали:
G>>У тройки тип Int, можно считать что это функция с нулем аргументов, которая возвращает себя, а может и ниче не возвращает, так как в типизированной лямбде для функций с нулем аргументов аппликация неприменима.
G>>Это только вопрос идеологии.
К>Что такое функция с нулём аргументов? Она применяется к юниту (нуль-арному кортежу) или вообще не применяется? К>Если не применяется — какая же это функция?
Но ведь
f :: Int
f = 1 + (3 + 3)
является функцией (не в математическом смысле, конечно)
Она даже выполняется (правда, только один раз; и оптимизатор вполне может её вычислить статически)
Prelude> :m + Debug.Trace
Prelude Debug.Trace> let f = 1 + (trace "called!" (3 + 3))
Prelude Debug.Trace> f
called!
7
Prelude Debug.Trace> f
7
Prelude Debug.Trace>
Мне кажется, утверждение "всё является функцией" основано на том, что такого рода сущности никак не выделены в языке. Хотя полезность такого обобщения, конечно, сомнительна (но и вреда особо не видно ).
Здравствуйте, D. Mon, Вы писали:
DM>Здравствуйте, gandjustas, Вы писали:
G>>Она возвращает константную функцию — число 3. Те возвращает сама себя.
DM>Вчера как раз подумал: кот — это устройство по превращению еды в кота, т.е. кот :: еда -> кот.
Здравствуйте, SolVolkov, Вы писали:
К>>Что такое функция с нулём аргументов? Она применяется к юниту (нуль-арному кортежу) или вообще не применяется? К>>Если не применяется — какая же это функция?
SV>Но ведь SV>f = 1 + (3 + 3) SV>является функцией (не в математическом смысле, конечно) SV>Она даже выполняется (правда, только один раз; и оптимизатор вполне может её вычислить статически)
Нуу, батенька!
int hello() { printf("hello!"); return 1+3+3; }
static int const x = hello();
void suddenly()
{
static int const y = hello();
}
Ни x, ни y не являются функциями, хотя, без сомнения, они требуют вычислений — вызова функций hello, printf и operator+.
Причём y — ленивое значение, оно будет вычислено только при первом вызове использующей её функции.
(А если убрать printf, то оптимизатор вполне может и проинлайнить, и вычислить статически).
SV>Мне кажется, утверждение "всё является функцией" основано на том, что такого рода сущности никак не выделены в языке. Хотя полезность такого обобщения, конечно, сомнительна (но и вреда особо не видно ).
Как это не выделены? Функции есть, значения есть, ленивость тоже есть.
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, SolVolkov, Вы писали:
К>>>Что такое функция с нулём аргументов? Она применяется к юниту (нуль-арному кортежу) или вообще не применяется? К>>>Если не применяется — какая же это функция?
SV>>Но ведь SV>>f = 1 + (3 + 3) SV>>является функцией (не в математическом смысле, конечно) SV>>Она даже выполняется (правда, только один раз; и оптимизатор вполне может её вычислить статически)
К>Нуу, батенька!
Я и не утверждал, что "она даже выполняется" -- это определение
К>
К>int hello() { printf("hello!"); return 1+3+3; }
К>static int const x = hello();
К>void suddenly()
К>{
К> static int const y = hello();
К>}
К>
К>Ни x, ни y не являются функциями, хотя, без сомнения, они требуют вычислений — вызова функций hello, printf и operator+. К>Причём y — ленивое значение, оно будет вычислено только при первом вызове использующей её функции. К>(А если убрать printf, то оптимизатор вполне может и проинлайнить, и вычислить статически).
int hello1() {return 1+3+3}
int hello2 = 7
hello1 -- функция с нулём аргументов. Или нет? Она ведь ни к чему не применяется.
f в моём примере -- аналог функции hello1.
SV>>Мне кажется, утверждение "всё является функцией" основано на том, что такого рода сущности никак не выделены в языке. Хотя полезность такого обобщения, конечно, сомнительна (но и вреда особо не видно ).
К>Как это не выделены? Функции есть, значения есть, ленивость тоже есть.
Где есть? И при чём тут ленивость?
Function binding семантически эквивалентно pattern binding. Вот и всё.
Т.е. следующие определения абсолютно идентичны
f2 a = a + 1 -- function binding
f2 = \a -> a + 1 -- pattern binding
f2 = (+1) -- pattern binding
В первом случае f2 биндится на function value, а в двух других -- просто на value. В чём разница между value и function value? Хз, в определении языка никакой разницы я не нашёл (вполне допускаю, впрочем, что плохо искал ).
Haskell Report не даёт определения понятию "функция", да и использует его непоследовательно. Поэтому вопрос, является ли "7" функцией или нет не имеет ответа. Это лишь вопрос предпочтений.
Можно пойти дальше и сказать, что в хаскеле всё является значением. И это тоже будет правдой.
И я так и не понял, в чем, собственно, причина столь большого резонанса по повожу сабжа? Что в этом утверждении плохого и неправильного?
SV>Function binding семантически эквивалентно pattern binding. Вот и всё. SV>Т.е. следующие определения абсолютно идентичны SV>
SV>f2 a = a + 1 -- function binding
SV>f2 = \a -> a + 1 -- pattern binding
SV>f2 = (+1) -- pattern binding
SV>
SV>В первом случае f2 биндится на function value, а в двух других -- просто на value. В чём разница между value и function value? Хз, в определении языка никакой разницы я не нашёл (вполне допускаю, впрочем, что плохо искал ).
Разница в том, что по умолчанию значения мономорфны, а функции полиморфны
f x = x+1 -- Num a => a->a
g = (+1) -- Integer->Integer
-- хотя можно и объявить явно
h :: (Fractional a) => a->a -- подойдёт любой субкласс Num :)
h = (+1)
i :: Int->Int-- подойдёт любой инстанс Num
i x = x+1
А в остальном — это сахар
SV>Haskell Report не даёт определения понятию "функция", да и использует его непоследовательно. Поэтому вопрос, является ли "7" функцией или нет не имеет ответа. Это лишь вопрос предпочтений.
Ну, если термин используется абы как, то предпочтительно было бы не вносить дополнительную сумятицу и не использовать его там, где в обычной жизни его бы не стали использовать.
SV>Можно пойти дальше и сказать, что в хаскеле всё является значением. И это тоже будет правдой.
Ну не всё, конечно. Классы и типы не являются первоклассными объектами. Но то, что является первоклассными — суть значения, по определению
SV>И я так и не понял, в чем, собственно, причина столь большого резонанса по повожу сабжа? Что в этом утверждении плохого и неправильного?
Дык, попытка сделать нечто неестественное. То, что не ложится ни в математическую семантику, ни в программистскую.
Вызывает естественный протест, во-первых, и всякие изыски, во-вторых.
Вот если бы мы разнесли понятия "хранилище" и "значение", причём значения не обязаны быть первоклассными объектами, а возникают постольку-поскольку внутри вычислений, как содержимое регистров...
А чтение хранилища сделать нуль-арной функцией.
Это привело бы к непротиворечивому, но жутко избыточному синтаксису
x = 3
y() = trace"y" `seq` 4()
f() = x() + 1() -- (+) здесь неполноценная встроенная функция, принимающая разбоксированные значения
g(z) = f() + z() -- раз мы пользуемся (+), то вынуждены разбоксировать аргумент
h() = g(y) -- а здесь боксированный аргумент и разбоксированный результат
Кажется, получается комонада... функции вида (box a -> a)
Свят-свят-свят...