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