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 даёт возможность разным элементам списка иметь разные типы, в отличие от первой функции
Люди, я люблю вас! Будьте бдительны!!!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.