Re[12]: ФП и абстракция списка
От: Кодт Россия  
Дата: 06.06.07 15:24
Оценка:
Здравствуйте, BulatZiganshin, Вы писали:

BZ>1) в compile time подставить тело print в каждую точку вызова и выбрать нужную реализацию show в каждой точке вызова отдельно. т.е. compile-time polymorphism. он реализуется в C++ механизмом overload и темплейтами, которые готовы в любой момент сгенерировать код для нужной комбинации типов. ты, как я порнимаю, до сих пор полагал, что type classes устроены так же


Ага.

BZ>2) сгенерить один-единственный type-independent code для print, и упаковать таблицу виртуальных функций (VMT) вместе с каждым объектом. это и есть ООП подход. когда print должна вызвать функию show — она лезет в VMT и берёт её адрес оттуда. таким образом, один-единственный откомпилированный экземпляр print может работать с любым объектом, реализующим этот интерфейс


BZ>3) также сгенерить один-единственный экземпляр print, но передавать информацию обо всех вызываемых полиморфных функиях в так назыавемом словаре класса — дополнительном невидимом аргументе. т.е. после дешугаринга этот вызов выглядит так:


Заодно стало понятно, как (правда, ценой косвенных вызовов) можно компилировать и экспортировать обобщённые функции.
Поскольку ещё на стадии вывода типов становится понятно предусловие о классах, ну скажем,
showfac n = show $ fac n
fac 0 = 1
fac n = n * fac (n-1)

:t fac
Num a => a -> a
:t showfac
Num a, Show a => a -> [Char]

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

BZ>как видишь, все функции класса просто идут в этом неявном аргументе. вот и всё. у этого подхода свои преимущества и недостатки, но главное для FP — что он в отличие от OO classes совместим с HM type inference. поскольку в OOP print может получить объект любого типа — всё определяется в run-time, и весь type inference на этом кончается.


В ООП print может получить объект не любого типа, а принадлежащего классу Show. Или, говоря по-ООП-шному, поддерживающему этот интерфейс.
Эта информация прекрасно выводится и соответствующим образом обуславливает пользователей функции print. Те, в свою очередь, обуславливают своих пользователей, и так далее.
Ну а конечный пользователь подсунет объект, проходящий через все эти фильтры, причём его методы обязаны возвращать объекты, фактические типы которых принадлежат ожидаемым классам.

BZ> с type classes же такой проблемы не возникает. зато, с другой стороны, нельзя например делать полиморфные коллекции без дополнительных ухищрений (фактически эмулирующих VMT)


А вот здесь я снова не понял.
Ясно, что когда VMT идёт отдельно от данных, то полиморфизм делается с велосипедным приводом.
Но когда VMT вместе с данными...
В определении fac всё, что можно сказать про n, n-1, fac(n-1) и их произведение — это то, что их фактические типы должны поддерживать интерфейс Num и начинаться от одной общей базы (поскольку у всех — одинаковый статический тип Num a => a). А как мультиметоды (-) и (*) будут заниматься скрещиванием — компилятору пофиг. Наверное, если пользователь подсунул в fac объект из какой-то вычурной иерархии имени Мичурина и Менделя, то он и мультиметоды смог написать.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[12]: ФП и абстракция списка
От: WolfHound  
Дата: 06.06.07 16:26
Оценка:
Здравствуйте, BulatZiganshin, Вы писали:

BZ>как видишь, все функции класса просто идут в этом неявном аргументе. вот и всё. у этого подхода свои преимущества и недостатки, но главное для FP — что он в отличие от OO classes совместим с HM type inference. поскольку в OOP print может получить объект любого типа — всё определяется в run-time, и весь type inference на этом кончается. с type classes же такой проблемы не возникает. зато, с другой стороны, нельзя например делать полиморфные коллекции без дополнительных ухищрений (фактически эмулирующих VMT)

Бред. Вывод типов в немерле надо пологать галюцинация?

Вывод типов не зависит от деталей реализации рантайма.
Совершенно всеравно как именно в рантайме передается информация о том какой именно метод дергать.
Ибо типы выводятся во время компиляции.
И в статически типизированных ОО языках вся информация о типах есть.

Проблема же состоит в том что разные интерфейсы могут содержать одинаковые функции.
И именно это, а не передача VMT вместе с объектом, мешает выводу типов.
Попробуй вывести типы в этом примере:
interface Foo1
{
    Foo(i : int) : int;
}
interface Foo2
{
    Foo(i : int) : int;
}
...
def Bar(foo)
{
    foo.Foo(1);
}


Но еслибы было запрещено делать одинаковые функции в разных интерфейсах то вывод типов был бы возможен.
В этом примере типы выводится с полпинка:
interface Foo1
{
    Foo(i : int) : int;
}
...
def Bar(foo)
{
    foo.Foo(1);
}


Также затрудняют вывод всякие перегрузки и неявные привидения типов.

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

А словарь методов передается отдельно по тому что в хаскеле можно реализовать класс типа для конкретного типа в любой момент, а не как в распространенных ОО языках только при объявлении типа.
Те в хаскеле банально трудно создать классическую VMT.
... << RSDN@Home 1.2.0 alpha rev. 673>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[13]: ФП и абстракция списка
От: deniok Россия  
Дата: 06.06.07 16:57
Оценка: 10 (1)
Здравствуйте, WolfHound, Вы писали:

WH>Здравствуйте, BulatZiganshin, Вы писали:


BZ>>как видишь, все функции класса просто идут в этом неявном аргументе. вот и всё. у этого подхода свои преимущества и недостатки, но главное для FP — что он в отличие от OO classes совместим с HM type inference. поскольку в OOP print может получить объект любого типа — всё определяется в run-time, и весь type inference на этом кончается. с type classes же такой проблемы не возникает. зато, с другой стороны, нельзя например делать полиморфные коллекции без дополнительных ухищрений (фактически эмулирующих VMT)


WH>Бред. Вывод типов в немерле надо пологать галюцинация?


Судя по тому, что написано здесь, вывод типов в Nemerle и HM type inference — весьма разные вещи. В Nemerle вывод направлен на поиск конкретного частного типа, удовлетворяющего всем ограничениям на тип. В HM type inference, наоборот, ищется наиболее общий тип, удовлетворяющий всем ограничениям.
Re[13]: ФП и абстракция списка
От: BulatZiganshin  
Дата: 06.06.07 16:58
Оценка:
WH>Бред. Вывод типов в немерле надо пологать галюцинация?

ты бы прежде чем высасывать чушь из пальца, поинтересовался хоть ограничениями type inference в немерле
Люди, я люблю вас! Будьте бдительны!!!
Re[14]: ФП и абстракция списка
От: WolfHound  
Дата: 06.06.07 17:05
Оценка:
Здравствуйте, deniok, Вы писали:

D>Судя по тому, что написано здесь, вывод типов в Nemerle и HM type inference — весьма разные вещи. В Nemerle вывод направлен на поиск конкретного частного типа, удовлетворяющего всем ограничениям на тип. В HM type inference, наоборот, ищется наиболее общий тип, удовлетворяющий всем ограничениям.

Я вобщемто объяснил что препятствует выводу общих типов.
... << RSDN@Home 1.2.0 alpha rev. 673>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[14]: ФП и абстракция списка
От: WolfHound  
Дата: 06.06.07 17:05
Оценка:
Здравствуйте, BulatZiganshin, Вы писали:

BZ>ты бы прежде чем высасывать чушь из пальца, поинтересовался хоть ограничениями type inference в немерле

Я о них знаю лучше тебя.
А еще я в отличии от тебя знаю почему так происходит.
... << RSDN@Home 1.2.0 alpha rev. 673>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[15]: ФП и абстракция списка
От: BulatZiganshin  
Дата: 06.06.07 17:26
Оценка: -1
Здравствуйте, WolfHound, Вы писали:

WH>Здравствуйте, BulatZiganshin, Вы писали:


BZ>>ты бы прежде чем высасывать чушь из пальца, поинтересовался хоть ограничениями type inference в немерле

WH>Я о них знаю лучше тебя.
WH>А еще я в отличии от тебя знаю почему так происходит.

молоджец, теперь возьми с полки пирожок и перестань рассуждать о том, чего не знаешь
Люди, я люблю вас! Будьте бдительны!!!
Re[15]: ФП и абстракция списка
От: deniok Россия  
Дата: 06.06.07 17:34
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Здравствуйте, deniok, Вы писали:


D>>Судя по тому, что написано здесь, вывод типов в Nemerle и HM type inference — весьма разные вещи. В Nemerle вывод направлен на поиск конкретного частного типа, удовлетворяющего всем ограничениям на тип. В HM type inference, наоборот, ищется наиболее общий тип, удовлетворяющий всем ограничениям.

WH>Я вобщемто объяснил что препятствует выводу общих типов.
Описанная тобой проблема легко решается квалифицированными именами.
Re[16]: ФП и абстракция списка
От: WolfHound  
Дата: 06.06.07 17:35
Оценка:
Здравствуйте, BulatZiganshin, Вы писали:

BZ>молоджец, теперь возьми с полки пирожок и перестань рассуждать о том, чего не знаешь

Это ты перестань говорить о том что не понимаешь. Ибо это ты утверждаешь что VMT внутри класса мешает выводу типов
Что мешает я написал.
Если не понятно ты скажи. Я еще раз объясню.
... << RSDN@Home 1.2.0 alpha rev. 673>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[16]: ФП и абстракция списка
От: WolfHound  
Дата: 06.06.07 17:37
Оценка:
Здравствуйте, deniok, Вы писали:

WH>>Я вобщемто объяснил что препятствует выводу общих типов.

D>Описанная тобой проблема легко решается квалифицированными именами.
Те фактически явным указанием типа.
... << RSDN@Home 1.2.0 alpha rev. 673>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[17]: ФП и абстракция списка
От: BulatZiganshin  
Дата: 06.06.07 17:47
Оценка:
BZ>>молоджец, теперь возьми с полки пирожок и перестань рассуждать о том, чего не знаешь
WH>Это ты перестань говорить о том что не понимаешь. Ибо это ты утверждаешь что VMT внутри класса мешает выводу типов
WH>Что мешает я написал.
WH>Если не понятно ты скажи. Я еще раз объясню.

ты ошибся. доступно излагаю? попытайся сначала разобраться как делается type inference прежде чем пытаться о нём рассуждать
Люди, я люблю вас! Будьте бдительны!!!
Re[17]: ФП и абстракция списка
От: deniok Россия  
Дата: 06.06.07 17:53
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Здравствуйте, deniok, Вы писали:


WH>>>Я вобщемто объяснил что препятствует выводу общих типов.

D>>Описанная тобой проблема легко решается квалифицированными именами.
WH>Те фактически явным указанием типа.
Неа, модуля. Это конфликт библиотек, а не типов.
Re[18]: ФП и абстракция списка
От: WolfHound  
Дата: 06.06.07 18:00
Оценка:
Здравствуйте, BulatZiganshin, Вы писали:

BZ>ты ошибся. доступно излагаю? попытайся сначала разобраться как делается type inference прежде чем пытаться о нём рассуждать

Если ты все понимаешь то тебе не составит труда объяснить что препятствует выводу типов в случае если в двух интерфейсах нельзя описать метод с одинаковой сигнатурой.
... << RSDN@Home 1.2.0 alpha rev. 673>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[18]: ФП и абстракция списка
От: WolfHound  
Дата: 06.06.07 18:05
Оценка:
Здравствуйте, deniok, Вы писали:

WH>>>>Я вобщемто объяснил что препятствует выводу общих типов.

D>>>Описанная тобой проблема легко решается квалифицированными именами.
WH>>Те фактически явным указанием типа.
D>Неа, модуля. Это конфликт библиотек, а не типов.
Но ведь в модуле нельзя в двух разных классах типов описать функции с одинаковыми сигнатурами.
... << RSDN@Home 1.2.0 alpha rev. 673>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[19]: ФП и абстракция списка
От: deniok Россия  
Дата: 06.06.07 18:15
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Здравствуйте, deniok, Вы писали:


WH>>>>>Я вобщемто объяснил что препятствует выводу общих типов.

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

Тут фишка в том, что объект в ООП "стягивает" на себя все свои интерфейсы. Он о них должен знать на этапе компиляции. А в Хаскелле не так. Int ни фига не знает, что он Typeable. И пока нам не пришло в голову воспользоваться для него
cast :: (Typeable a, Typeable b) => a -> Maybe b

подключив модуль Data.Typeable, то это знание ни самому Int, ни функциям, этот Int использующим, ни на фиг не упало.
Re[19]: ФП и абстракция списка
От: BulatZiganshin  
Дата: 06.06.07 18:39
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Здравствуйте, BulatZiganshin, Вы писали:


BZ>>ты ошибся. доступно излагаю? попытайся сначала разобраться как делается type inference прежде чем пытаться о нём рассуждать

WH>Если ты все понимаешь то тебе не составит труда объяснить что препятствует выводу типов в случае если в двух интерфейсах нельзя описать метод с одинаковой сигнатурой.

проблема в том, что вы вообще не с той стороны пляшете. синтаксис второстепенен, главное — какие возможности предлагает семантика, "объектная модель". я это несколько рахз объянял Владу, затем Сергую, наконец Кодту. очему бы тебе не прочитать внимательней? и тогда станет ясно, что дело не в синтаксисе, а в том, что во время выполнения просто не сущетсвует информации, необходимой для реализации функции, аналогичной моему nul. а все синтаксические возможности немерле или любого другого ООП языка — это всего лишь средство, предоставляющее доступ ровно к тем влзможностям, которые даёт данная объектная модель. семантика — первична, синтаксис — вторичен
Люди, я люблю вас! Будьте бдительны!!!
Re[13]: ФП и абстракция списка
От: BulatZiganshin  
Дата: 06.06.07 19:33
Оценка: 25 (2)
К>Заодно стало понятно, как (правда, ценой косвенных вызовов) можно компилировать и экспортировать обобщённые функции.

да, именно так type classes в этом отношении полностью соотвествуют ОО classes, а никак не templates. хотя на практике их можно заинлайнить прагмой, так что в нынешнем GHC есть и поддержка аналога компилированных темплейтов. с одной стороны получается удобно, что один и тот же синтаксис и на compile-time, и на run-time полиморфизм (в отличие от С++), с другой стороны, директива — это не какое-то строгое обязательство, и когда компилятор из-за своих ограничений отказывается что-либо инлайнить... у меня как-то скорость программы упала в 200 раз из-за одной пропцщенной директивы

К>Поскольку ещё на стадии вывода типов становится понятно предусловие о классах, ну скажем,


да, всё именно так — требования к классам входят в тип (поскольку словари каждого класса придётся передать отдельным аргументом) и выводятся из требований использованных операций — всё это рекурсивно вплоть до операций, непосредственно объявленных в классах


BZ>>как видишь, все функции класса просто идут в этом неявном аргументе. вот и всё. у этого подхода свои преимущества и недостатки, но главное для FP — что он в отличие от OO classes совместим с HM type inference. поскольку в OOP print может получить объект любого типа — всё определяется в run-time, и весь type inference на этом кончается.


К>В ООП print может получить объект не любого типа, а принадлежащего классу Show. Или, говоря по-ООП-шному, поддерживающему этот интерфейс.

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

ладно, это сработает, но для практического применения HM type inference прицнипиально важно, что он работает в обе стороны. поэтому информация о типах должна быть вынесена в compile-time. динамичсекая типизация, допускаемая в ООП, является здесь непозволительной роскошью:

[ccode]
Figure *create()
{
switch (getch()) {
case 'a': return new Triangle;
case 'b': return new Circle;
}
}
[/code]

поэтому и появилась объектная модель, делающая такую роскошт невозможной



BZ>> с type classes же такой проблемы не возникает. зато, с другой стороны, нельзя например делать полиморфные коллекции без дополнительных ухищрений (фактически эмулирующих VMT)


К>А вот здесь я снова не понял.


полиморфные коллекции — это соджержащие объекты разных типов, реализующих общий интерфейс. пусть скажем, это фигуры, которые можно рисовать на экране — треугольники, овалы и т.д. если каждый объект включает свою собственную VMT, то из неё вы узнаёте, как нарисовать это конкретный объект. если же вы перелаёте одну VMT на всё-про всё, то нифига хорошего не выйдет реализация этого требует так называемых existentials, которые включают VMT класса вместе с каждым объектом:

diplayAll1 :: Figure a =>   [a] -> IO ()
diplayAll2 :: [exist a . Figure a => a] -> IO ()


первое определение означает, что в процедуру передаётся список однотипных фигур. т.е. либо все треугольники, либо все овалы с одним словарём на всех. второе — что передаётся список оо-подобных объектов, каждый со своим собственным словарём. после рассахаривания это выглядит так:

type figure a  =  a -> IO ()
diplayAll1 :: figure a -> [a] -> IO ()
diplayAll2 :: [exist a . (figure a, a)] -> IO ()


"figure a" здесь — тип словаря для класса Figure, cостоящий в данном случае из одной-единственной функции. ну а квантор exists даёт возможность разным элементам списка иметь разные типы, в отличие от первой функции
Люди, я люблю вас! Будьте бдительны!!!
Re[20]: ФП и абстракция списка
От: WolfHound  
Дата: 06.06.07 20:44
Оценка:
Здравствуйте, deniok, Вы писали:

D>С одинаковыми названиями? Нельзя.

Именно это ограничение и позволяет выводить типы на право и на лево.
Тк нет функций с одинаковыми именами то встречая функцию с определенным именем мы точно знаем какой класс типа взять.
А еслибы этого ограничения небыло то привет...
Хотя тут можно генерить перегрузки на каждый интерфейс.
Те из такого
interface Foo1
{
    Foo(i : int) : int;
}
interface Foo2
{
    Foo(i : int) : int;
}
...
def Bar(foo)
{
    foo.Foo(1);
}

получаем такое
interface Foo1
{
    Foo(i : int) : int;
}
interface Foo2
{
    Foo(i : int) : int;
}
...
def Bar(foo : Foo1) : int
{
    foo.Foo(1);
}

def Bar(foo : Foo2) : int
{
    foo.Foo(1);
}

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

D>А зачем в модуле разные функции называть одинаково?

Это уже другой вопрос.

D>Тут фишка в том, что объект в ООП "стягивает" на себя все свои интерфейсы. Он о них должен знать на этапе компиляции. А в Хаскелле не так. Int ни фига не знает, что он Typeable. И пока нам не пришло в голову воспользоваться для него

D>
D>cast :: (Typeable a, Typeable b) => a -> Maybe b
D>

D>подключив модуль Data.Typeable, то это знание ни самому Int, ни функциям, этот Int использующим, ни на фиг не упало.
Это я понимаю.
Я не понимаю как "стягивание" интерфейсов на себя мешает выводу типов.
... << RSDN@Home 1.2.0 alpha rev. 673>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[20]: ФП и абстракция списка
От: geniepro http://geniepro.livejournal.com/
Дата: 06.06.07 21:52
Оценка: :)
Здравствуйте, BulatZiganshin, Вы писали:

BZ> семантика — первична, синтаксис — вторичен


Предлагаю перейти с Хаскелла на Лискелл!
Семантика хаскелловская, синтаксис... Синтаксис вторичен! :о))
Re[21]: ФП и абстракция списка
От: deniok Россия  
Дата: 06.06.07 22:34
Оценка:
Здравствуйте, WolfHound, Вы писали:

D>>Тут фишка в том, что объект в ООП "стягивает" на себя все свои интерфейсы. Он о них должен знать на этапе компиляции. А в Хаскелле не так. Int ни фига не знает, что он Typeable. И пока нам не пришло в голову воспользоваться для него

D>>
D>>cast :: (Typeable a, Typeable b) => a -> Maybe b
D>>

D>>подключив модуль Data.Typeable, то это знание ни самому Int, ни функциям, этот Int использующим, ни на фиг не упало.
WH>Это я понимаю.
WH>Я не понимаю как "стягивание" интерфейсов на себя мешает выводу типов.

Во-первых.

class Stack s e where
push :: s -> e -> s
pop  :: s -> s
top  :: s -> e


На какой объект в рантайме будет "стягиваться" этот обобщенный интерфейс? На конкретную реализацию контейнера s или на конкретную реализацию элемента e?

Во-вторых.
Ещё раз повторяю, что алгоритм вывода HM ищет наиболее общий (principle) тип, то есть подходящий для выражения тип максимально обобщённого характера. Причём это касается не только выражений зацепляющих "интерфейсы", но и выражений без ограничений. Тип оператора композиции
(.) f g x = f( g x)

таков
(.) :: (b -> c) -> (a -> b) -> a -> c

Всё, вывод типа для выражения успешно завершён, principle type найден.

В Немерле, как я понимаю, речи о principle type не идёт. То есть вывод типов направлен на максимальную конкретизацию результата для типа объекта, а не в сторону максимального обобщения для типа выражения.
Причём остающийся для рантайма полиморфизм, как я понял отсюда, связан исключительно с наследованием одного класса от другого.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.