migmit: (Default)
[personal profile] migmit

Вот есть хаскельный код (пример упрощён до предела):

data P a = P a (forall b. b -> P (a, b))
Нормально компилится, если указать прагму LANGUAGE RankNTypes в GHC или ключик -98 в Hugs-е.
Можно написать несколько "генераторов" для такого P:
sameValue :: a -> P a
sameValue x = P x (\y -> sameValue (x, y))

firstRest :: a -> a -> P a
firstRest x y = P x (\z -> sameValue (y, z))

switching :: a -> a -> P a
switching x y = P x (\z -> switching (y, z) (x, z))
Как сделать это на C++???
Я попробовал, моего плюс-фу не хватило. Светилы, если вы есть, можете подсказать?
Хочется что-то вроде этого:

#include <map>
template <class A> class P {
  A car;
  template <class B> virtual P<std::pair<A,B> > cdr (B) = 0;
};

Не заработает, ибо template и virtual вместе не живут. Убрать virtual нельзя - класс определяется как абстрактный, реализация функции cdr будет разной (см. выше), но эту разницу надо скрыть "под капотом", указывая везде базовый класс.
Как?

Originally posted on migmit.vox.com

Date: 2009-02-05 11:15 am (UTC)
From: [identity profile] migmit.vox.com (from livejournal.com)
То, что template virtual не пройдёт - это ёжику понятно.

Скажу по секрету, я даже в курсе, что мой тип P изоморфен такому:
data P1 a = P1 a (P1 a)
а функцию можно написать отдельно:
cdr :: P1 a -> b -> P1 (a, b)
cdr (P1 x p) y = P1 (x, y) $ cdr p y
Из свободных теорем как-нибудь должно следовать, что они изоморфны - в конце концов, на y никакие ограничения не накладываются, так что ничего, кроме как всё время возвращать его же, мы сделать не в состоянии (не совсем правда, можно ещё жопу возвращать - ленивый язык возражать не будет).

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

Date: 2009-02-05 11:37 am (UTC)
From: [identity profile] mr-aleph.livejournal.com
о, мой мозг...

мой основной поинт в том, что для C++ не существует аналога forall в принципе.

Date: 2009-02-05 06:47 pm (UTC)
From: [identity profile] migmit.vox.com (from livejournal.com)
Шо-то наглючил я с этой cdr, она иначе пишется. Но суть та же.

Фишка в том, что, убрав virtual, я как раз и получаю forall. Но непереопределяемый.

Date: 2009-02-05 06:49 pm (UTC)
From: [identity profile] mr-aleph.livejournal.com
не совсем, в Haskell ежели написано forall, то это именно forall, статически доказанный.
В C++ ты можешь там написать зюзюзю(b) и всё будет окей, до тех пор пока ты непопробуешь передать туда B для которого нет зюзюзю(b)

Date: 2009-02-05 07:39 pm (UTC)
From: [identity profile] migmit.vox.com (from livejournal.com)
Тру, однако. Вообще как-то мне кажется, что статическая типизация в C++ - это такой обман.