LINUX.ORG.RU

[haskell] есть ли что-то типа reflection? (недемократизм языка?)

 


0

0

Обычная фраза: deriving (Read, Show, Eq, Ord)

Компилятор умеет выводить инстансы этих typeclass-ов. А что делать, если хочется их выводить чуть-чуть по-другому или добавить еще один, который автоматически бы выводился? (Для этого, возможно, подошло что-то похожее на reflection, патчить компилятор не предлагайте)

__________________________________________________

Недемократизм языка в моем понимании -- это

1. Частичная реализация некой фичи и одновременно отстутствие инструмента для расширения реализации этой фичи. Например в яве оператор + для сложения целых, вещественных, строк и все: комплексные, кватернионы, вектора, матрицы... складывай уже через add.

2. Невозможность смены конкретной реализации фичи (зачастую связано с п.1). Например, невозможность создать в рамках с++ свой virtual dispatch (для того, что сделать множественный virtual dispatch, т.е. п.1). В принципе, п.2 до некоторой степени неизбежен, так как иногда намного проще сделать фичу, чем API для написания фич).

__________________________________________________

Более глобальный вопрос -- а насколько хаскель демократичен? (для обеспечения демократизма разрешается использовать ключи компилятора, template haskell, ...)

Ответ на: комментарий от wfrr

рефлекшен в яве говно минимум по 2 причинам -- он позволяет легко нарушить инкапсуляцию (всеобщий запрет на доступ через рефлекшен к приватным членам -- это полумера) и он не type-safe (в смысле, компилятор не может проверить типизацию обращений через рефлекшен)

www_linux_org_ru ★★★★★
() автор топика

Это точно нельзя сделать стандартным хаскелем.

Наверное можно с template haskell, но я не знаю...

Waterlaz ★★★★★
()

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

не знаю. однако хороший вопрос, посмотрю

>насколько хаскель демократичен?

а по какой шкале мерять? то есть для меня ответ "да", но я не знаю, насколько он подходит тебе :)

jtootf ★★★★★
()
Ответ на: комментарий от jtootf

> а по какой шкале мерять? то есть для меня ответ "да", но я не знаю, насколько он подходит тебе

ну если даже с template haskell нельзя, то ответ однозначно "нет"

независимо от шкалы, интересуют остальные проявления недемократичности хаскеля

www_linux_org_ru ★★★★★
() автор топика
Ответ на: комментарий от jtootf

э... я пропустил вот это:

>не знаю. однако хороший вопрос, посмотрю

если *статически проверяемый* аналог рефлексии или что-то в этом духе, пригодное для построения своего кастомного show имеется, то пример недемократичности отменяется

www_linux_org_ru ★★★★★
() автор топика

В хаскеле нет доступа к компилятору, нет полноценных макросов, т.е. вменяемой compile-time рефлекшн нет и не построить.
 
В рантайме все еще хуже.

guest-3484-2009
()
Ответ на: комментарий от guest-3484-2009

> В хаскеле нет доступа к компилятору, нет полноценных макросов, т.е. вменяемой compile-time рефлекшн нет и не построить.

А в лиспе все еще хуже, т.к. нет статической типизации.

Если мне нужен аналог макросов, то перл в руки и генерю код, который потом статически тестируется компилятором (С++ или хаскеля). А в лиспе разница лишь та, что макросы пишутся не на перле, а на самом лиспе (очень сомнительный профит), и статического тестирования нет (явно хуже).

www_linux_org_ru ★★★★★
() автор топика
Ответ на: комментарий от www_linux_org_ru

>т.к. нет статической типизации. А это нахрен не надо в большинстве случаев. А если приперло, для какой-то конкретной задачи можно написать DSL, некую специфическую для задачи статическую типизацию вводящий. В целом же, динамическая типизация, по типу коммонлисповской - намного более гибка, чем даже хаскелевская статика. Она просто работает, если угодно. Статика же, по крайней мере, современный подход к ней, не позволит работать чему-то, что она не сможет верифицировать, пусть даже это что-то на самом деле и работало бы без проблем. >то перл в руки и генерю код Ты не врубаешься в макросы. Вся фишка макросов перед препроцессорами, "perl в руки" и другим подобным - возможность многоуровневые конструкции строить. Макросы, раскрывающиеся в другие макросы, и так далее. Ну и полный доступ к рантайму лиспа, естественно, т.е, как минимум, возможность стейт проносить от одного файла к другому, или даже внутри одного файла, в компайл-тайм, да еще и часть этого стейта, которую позволяет отдельный рантайм, дампнуть в fasl, а другую часть, к примеру, запихнуть раскрыть в eval-when, чтоб пронести необходимые вычисления в ран-тайм или лоад-тайм, или тут же прямо использовать при следующих макроэкспандах. >статического тестирования нет Тестирования чего? Опечаток по типу как бы корову с комплексным числом случайно не сложил? Статические тайпчекеры могут проверить корректность только в самых-самых примитивных случаях, вот как про корову выше. А даже те же макросы предоставляют гораздо большие возможности по статической верификации, чем тайпчекеры.

anonymous
()
Ответ на: комментарий от anonymous

Извиняюсь, отступы похерились.
>т.к. нет статической типизации.

А это нахрен не надо в большинстве случаев. А если приперло, для какой-то конкретной задачи можно написать DSL, некую специфическую для задачи статическую типизацию вводящий. В целом же, динамическая типизация, по типу коммонлисповской - намного более гибка, чем даже хаскелевская статика. Она просто работает, если угодно. Статика же, по крайней мере, современный подход к ней, не позволит работать чему-то, что она не сможет верифицировать, пусть даже это что-то на самом деле и работало бы без проблем.
>то перл в руки и генерю код

Ты не врубаешься в макросы. Вся фишка макросов перед препроцессорами, "perl в руки" и другим подобным - возможность многоуровневые конструкции строить. Макросы, раскрывающиеся в другие макросы, и так далее. Ну и полный доступ к рантайму лиспа, естественно, т.е, как минимум, возможность стейт проносить от одного файла к другому, или даже внутри одного файла, в компайл-тайм, да еще и часть этого стейта, которую позволяет отдельный рантайм, дампнуть в fasl, а другую часть, к примеру, запихнуть раскрыть в eval-when, чтоб пронести необходимые вычисления в ран-тайм или лоад-тайм, или тут же прямо использовать при следующих макроэкспандах.
>статического тестирования нет

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

anonymous
()

> есть ли что-то типа reflection?

Есть. Называется Data.Typeable и, главное, Data.Data. Есть пакет derive, который как раз занимается автоматическим выводом инстансов (кроме Read, Show, Eq, Enum, Ord, Data и Typeable), при помощи именно этой фичи.

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

Miguel ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

> Если мне нужен аналог макросов, то перл в руки и генерю код

Я понимаю твой скептицизм относительно лиспа и всемогущества макр, но вот аналог действительно не получится :)

1. Как минимум, нет у тебя в других языках без макроподдержки gensym - поэтому будет возможность name clashes и захвата переменных, а значит - либо придумывать страшные названия для локальных переменных и надеятся на чудо, либо создавать систему, эти самые name clashes разрешающее;

2. Я верю в m4 - но в некоторых случаях (питон, хаскелл) - он бесполезен, ибо просто вставить не получится (нужно строго соблюдать уровень индентации) - а значит, нужно писать писать свой макроподстановщик;

3. Даже для простейших конструкций (e.g. with-open-file (){} для сей) нужен будет лексический анализатор;

4. Вещи типа лисповых reader-macros или compiler-macros - тоже просто так не сделаешь, если язык их не поддерживает.

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

> и статического тестирования нет (явно хуже)

Есть в каком-то виде в sbcl (type inference). Были умельцы, которые делали отдельные средства статического анализа для лиспа - т.е. оно в принципе возможно.

> А в лиспе разница лишь та, что макросы пишутся не на перле,

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

anonymous
()
Ответ на: комментарий от www_linux_org_ru

> в смысле, компилятор не может проверить типизацию обращений через рефлекшен

А вообще такое в принципе-то возможно? Тут мне кажется либо рефлекшн (а значит и динамизм), либо type-safety.

anonymous
()

Хаскель это платформа для тестирования формльных выкладок на практике, не стоит к нему так серьезно относиться.

>Например в яве оператор + для сложения целых...

Оператор "+" по-хорошему годится только для примитивных типов. Для сложных типов выражение "+" уже не отображает никакой сути (add тоже не годится). Хороший пример - переопределения оператора "*" для матрицы. хотя матрицы можно умножать как и стандартным методом, так и поэлементно.

dizza ★★★★★
()
Ответ на: комментарий от anonymous

> В целом же, динамическая типизация, по типу коммонлисповской - намного более гибка, чем даже хаскелевская статика.

Знаешь, есть одна штука, которая в гибком состоянии значительно менее полезна, чем в жёстком. Примерно у половины населения земли наличествует.

> возможность стейт проносить от одного файла к другому

Ой, как это навернётся даже при мелком рефакторинге!..

> Статические тайпчекеры могут проверить корректность только в самых-самых примитивных случаях

Не видел ты настоящих статических тайпчекеров.

Miguel ★★★★★
()
Ответ на: комментарий от anonymous

> Я верю в m4 - но в некоторых случаях (питон, хаскелл) - он бесполезен, ибо просто вставить не получится (нужно строго соблюдать уровень индентации)

Я не верю, но никаких проблем писать do {name <- readLine; putStrLn $ "Hi, " ++ name} в хаскеле нет. Питон - да, там траблы.

> для нормального метапрограммирования (аналог лиспового) - _нужны_ средства поддержки этого самого метапрограммирования в самом языке

Луговский, помнится, где-то сказал, что частичное применение функций даёт то же, что и метапрограммирование.

Miguel ★★★★★
()
Ответ на: комментарий от anonymous

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

2. м4 я и не предлагал, это черная магия и уродство

3. поподробней плиз, кроме того, речь *не* идет о сях, а о языках типа плюсов и хаскеля

4. такие вещи либо неплохо эмулируются перлом, либо не нужны -- а там где все же нужны, надо будет юзать не перл, а делать свой лексер, парсер, и генератор кода в с++ (и это отдельная совсем тема)

www_linux_org_ru ★★★★★
() автор топика
Ответ на: комментарий от anonymous

> А вообще такое в принципе-то возможно? Тут мне кажется либо рефлекшн (а значит и динамизм), либо type-safety.

Да, можно, в нескольких вариантах. Как-нить напишу.

www_linux_org_ru ★★★★★
() автор топика
Ответ на: комментарий от Miguel

> и, главное, Data.Data

да, похоже оно. придется изучать.

www_linux_org_ru ★★★★★
() автор топика
Ответ на: комментарий от KRoN73

> А кто мешает прикрутить обёртку с проверкой типов?

Флаг тебе в руки. Обертка будет примерно величиной в 80% компилятора хаскеля или плюсов... по выбору.

www_linux_org_ru ★★★★★
() автор топика
Ответ на: комментарий от www_linux_org_ru

в 80% компилятора хаскеля или 40% компилятора плюсов

// Fixed.

www_linux_org_ru ★★★★★
() автор топика
Ответ на: комментарий от www_linux_org_ru

>Флаг тебе в руки. Обертка будет примерно величиной в 80% компилятора хаскеля или плюсов... по выбору.

Наверное, мы о чём-то разном. Обёртка в рантайме - это несколько строк. Про неё и говорю. Обёртка на этапе компиляции - невозможна, ИМХО, в общем случае. Я могу из внешнего источника подавать произвольный набор классов и методов, и только при исполнении можно проверить их корректность.

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

> Наверное, мы о чём-то разном. Обёртка в рантайме - это несколько строк.

Про обертку в рантайме я не стал бы и спрашивать.

> Про неё и говорю. Обёртка на этапе компиляции - невозможна, ИМХО, в общем случае.

возможна

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

Это в основном poor's man toolkit

www_linux_org_ru ★★★★★
() автор топика
Ответ на: комментарий от www_linux_org_ru

>возможна

Как? Если тип исходных внешних данных для рефлексии в общем случае может быть разным.

...

Ну, от балды: из внешнего файла (строчного) подаётся список имён классов и параметры для их инициализации, чтобы в рантайме эти классы загрузить класслоадером, инициализировать данными и добавить в систему. Пусть для конкретики это будет набор классов 2D и 3D объектов с параметрами размеров и положений и нужно их нарисовать. Набор классов заранее не фиксирован и может расширяться при исполнении.

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

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

проверять непонятно откуда всявшиеся "параметры для их инициализации" -- надо конечно, но это обычные проверки входных данных

(огрубляя немного, можно считать, что они даны в XML, схема которого сгенерена из исходников -- тогда "параметры для их инициализации" можно вообще не проверять)

www_linux_org_ru ★★★★★
() автор топика
Ответ на: комментарий от www_linux_org_ru

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

Так это тот же рантайм получится :)

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

> Так это тот же рантайм получится :)

Нет. Тема интересная, заслуживает обсуждения, так что возможно тебе стоит поподрбонее описать несколько юз кейсов (типа вкомпиленный в программу дебаггер, ...) а я приведу POC на плюсах.

www_linux_org_ru ★★★★★
() автор топика
Ответ на: комментарий от Miguel

> Не видел ты настоящих статических тайпчекеров.

Это те, на которых можно факториалы считать? :)

anonymous
()
Ответ на: комментарий от anonymous

> Это те, на которых можно факториалы считать? :)

Ты лучше скажи, много ли библиотек твоего лиспа аннотированы под твой супер-навороченный тайпечекер.

www_linux_org_ru ★★★★★
() автор топика
Ответ на: комментарий от Miguel

> Я не верю, но никаких проблем писать do {name <- readLine; putStrLn $ "Hi, " ++ name} в хаскеле нет.

Там нет проблем, потому что есть Template Haskell. Ну и к тому же не все же макросы однострочники, и при _тупой_ подстановке, как предлагал ОП, много чего может поламаться.

> Луговский, помнится, где-то сказал, что частичное применение функций даёт то же, что и метапрограммирование.

Весьма спорная точка зрения. Как минимум нужны еще ленивые вычисления :). С ходу придумать пример, где бы этот тезис не выполнялся не могу. Как придумаю - напишу :)

anonymous
()
Ответ на: комментарий от www_linux_org_ru

> Ты лучше скажи, много ли библиотек твоего лиспа аннотированы под твой супер-навороченный тайпечекер.

Я вообще-то про хаскелл :) Ну и кроме того, я не вижу особой необходимости в статической типизации, необходимость в _хороших_ средствах статического анализа - вижу.

anonymous
()
Ответ на: комментарий от www_linux_org_ru

> 1. клэши на крайняк обходятся названиями типа _lqmerilfsa, но обычно этого не нужно (как например для рефлекшена), т.к. генерить нужно классы целиком, а их можно класть в неймспейсы

Ну вот придумал ты свое имя, и тут сразу встает проблема вложенных друг в друга макросах. Нужен будет пример - приведу :)

> 3. поподробней плиз, кроме того, речь *не* идет о сях, а о языках типа плюсов и хаскеля

В типа хаскелле есть TH, в типа сях++ есть шаблоны - т.е. там уже есть средства метапрограммирования. А так опять возникают сложности при вложенных друг в друга одинаковых макросах и подсчете скобочного баланса :)

> 4. такие вещи либо неплохо эмулируются перлом, либо не нужны -- а там где все же нужны, надо будет юзать не перл, а делать свой лексер, парсер, и генератор кода в с++ (и это отдельная совсем тема)

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

anonymous
()
Ответ на: комментарий от anonymous

> Я вообще-то про хаскелл :) Ну и кроме того, я не вижу особой необходимости в статической типизации, необходимость в _хороших_ средствах статического анализа - вижу.

Вас, анонимусов, легко спутать. Так много ли лисповых библиотек идет аннотированными под твое "средство статического анализа"? Или оно чисто внутренного пользования -- тогда его ценность близка к 0.

www_linux_org_ru ★★★★★
() автор топика
Ответ на: комментарий от www_linux_org_ru

> Да, можно, в нескольких вариантах. Как-нить напишу.

Как? Опиши плиз поподробней.

anonymous
()
Ответ на: комментарий от www_linux_org_ru

> Так много ли лисповых библиотек идет аннотированными под твое "средство статического анализа"?

Там аннотировать нечего специально не надо - declare type уже есть в языке.

> Или оно чисто внутренного пользования -- тогда его ценность близка к 0.

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

Кстати тот же хаскеллевый обуенный тайпчекер (которой полон по тьюрингу и посему на некоторых программах может зависнуть) может вывалится в ран-тайма с non-exhausive pattern, правда круто?

anonymous
()
Ответ на: комментарий от anonymous

> 1. Ну вот придумал ты свое имя, и тут сразу встает проблема вложенных друг в друга макросах. Нужен будет пример - приведу :)

Приведи, только не виде лисповского кода, а описав словами.

п.2 вроде как закрыли :-)

> 3. В типа хаскелле есть TH, в типа сях++ есть шаблоны - т.е. там уже есть средства метапрограммирования. А так опять возникают сложности при вложенных друг в друга одинаковых макросах и подсчете скобочного баланса :)

Уж как-нибудь пересчитаю скобки :-) проблема не в них, а в том, что средства МП не дают доступ в случае С++ допустим к наличию локальной переменной с данным именем в данном блоке.

> 4. Потребности в колбасе нет, так и запишем. неплохо - это до тех пор, пока ты не начнешь писать что-то более или менее нетривиальное.

*Еще* раз говорю -- я не собрался писать DSL сильно отличающийся от языка. Опять представь, что я хочу рефлекшн в плюсах не через dwarf, а таким особым способом -- через спец. шаблоны. Так что действительно потребности нет.

> Ну вот я тебе и говорю - писать свой парсер, лексер, генератор - оно тебе надо?,

не надо, уже писал

> а потом в нем еще искать баги, не легче взять ocaml с нормальной поддержкой мп?

в ocaml + occamlp есть прямые аналоги тайпклассов хаскеля или (несостоявшихся) концептов с++ ?

www_linux_org_ru ★★★★★
() автор топика
Ответ на: комментарий от www_linux_org_ru

> в ocaml + occamlp есть прямые аналоги тайпклассов хаскеля или (несостоявшихся) концептов с++ ?

В окамле, к сожалению, нет. А они тебе _очень_ сильно нужны? :). Но они есть в ... лиспе :). Тайпклассы - это ровно тоже самое, что классы и generic функции в lisp'e, только без inheritance и без статической типизации (так что они тебе не подходят). На остальное отвечу позже, ибо дела.

anonymous
()
Ответ на: комментарий от anonymous

> Кстати тот же хаскеллевый обуенный тайпчекер (которой полон по тьюрингу и посему на некоторых программах может зависнуть) может вывалится в ран-тайма с non-exhausive pattern, правда круто?

А откуда уверенность, что твой велосипед статического анализа получится не полон по тьюрингу , не вывалится с эксепшеном, ... ?

Ладно, всем анонимусам отвечу, а сейчас беру таймаут.

www_linux_org_ru ★★★★★
() автор топика
Ответ на: комментарий от www_linux_org_ru

> А откуда уверенность, что твой велосипед статического анализа получится не полон по тьюрингу , не вывалится с эксепшеном, ... ?

Я не правильно написал, не сам тайп-чекер вываливается, а _программа во время исполнения_, и тайп-чекер это не предотвращает (даже варнинг не выдает, в окамле, что самое забавное - варнинг есть), несмотря на заявления хаскеллистов, о том, что у них не бывает "segmentation faults".

> А откуда уверенность, что твой велосипед статического анализа получится не полон по тьюрингу

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

anonymous
()
Ответ на: комментарий от anonymous

>Тайпклассы - это ровно тоже самое, что классы и generic функции в lisp'e, только без inheritance и без статической типизации

О господи! Аналогом типкласса является интерфейс в яве или абстрактный класс без полей в С++. Только типкласс не является типом в отличие от.

Про наследование - 4.2. Наследование в хаскеле есть, просто оно отличается от ООП (оно и понятно).

В Окамле есть отличная система модулей, поэтому типклассы в окамле не очень-то и нужны.

Macil ★★★★★
()
Ответ на: комментарий от Macil

> Только типкласс не является типом в отличие от.

И что это меняет?

> от.Про наследование - 4.2. Наследование в хаскеле есть, просто оно отличается от ООП (оно и понятно).

Наследование там только "интерфейсов", наследования данных там нет, это я и имел ввиду.

anonymous
()
Ответ на: комментарий от Macil

> В Окамле есть отличная система модулей, поэтому типклассы в окамле не очень-то и нужны.

А зачем они тогда нужны, если

> Аналогом типкласса является интерфейс в яве или абстрактный класс без полей в С++.

anonymous
()
Ответ на: комментарий от anonymous

>И что это меняет?

>Наследование там только "интерфейсов", наследования данных там нет, это я и имел ввиду.


Правильно. Типкласс НЕ является типоми. Поэтому там и нет явного наследования "данных".

Macil ★★★★★
()
Ответ на: комментарий от anonymous

>А зачем они тогда нужны

Для реализации абстрактных типов данных, вестимо.

Macil ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.