Re[10]: Классы типов
От: jazzer Россия Skype: enerjazzer
Дата: 01.11.14 11:03
Оценка:
Здравствуйте, samius, Вы писали:

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


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


J>>А сама статья есть где-нибудь? А то по ссылке только то, что она цитирует...

S>у меня там же ссылка на PDF видна

Спасибо! (у тебя ссылка слегка битая, поправь).

Ну там как раз и говорится:

Haskell type classes and various extensions can be emulated in C++ by C++ templates/traits and some amount of compile-time metaprogramming. ...C++ can easily handle other possible extensions to Haskell type classes.

jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[11]: Классы типов
От: Klapaucius  
Дата: 01.11.14 13:25
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Ну там как раз и говорится:

J>

J>Haskell type classes and various extensions can be emulated in C++ by C++ templates/traits and some amount of compile-time metaprogramming. ...C++ can easily handle other possible extensions to Haskell type classes.


Что тут удивительного? C++ "эмулирует" средства, добавляемые в язык с параметрическим полиморфизмом для того, чтоб получить ad-hoc полиморфизм. Т.е. полиморфизм, который в С++ основной. Правильнее было бы, наверное, сказать, что это хаскель "эмулирует" C++ средства.
Удивительно было бы, если бы C++ не "эмулировал" то, что в нем и так есть, а — наоборот — то, чего в нем нет — т.е. параметрический полиморфизм.
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Re[3]: Классы типов
От: Klapaucius  
Дата: 01.11.14 13:32
Оценка:
Здравствуйте, jazzer, Вы писали:

Ох, опять двадцать пять.

sum :: forall a. Add a => [a] -> a


А какая сигнатура у вашей sum?

J>template<class a>
J>int sum(vector<a> v) {
J>  return std::accumulate( std::begin(v), std::end(v), Add<a>::plus, Add<a>::zero() );
J>}


Вы ее, например, попробуйте на псевдохаскеле написать и сразу все ясно станет.
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Re[11]: Классы типов
От: samius Япония http://sams-tricks.blogspot.com
Дата: 01.11.14 13:48
Оценка:
Здравствуйте, jazzer, Вы писали:

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


S>>у меня там же ссылка на PDF видна


J>Спасибо! (у тебя ссылка слегка битая, поправь).

Не выходит. вставляю
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.78.2151&rep=rep1&type=pdf

получаю в превью
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.78.2151&amp;rep=rep1&amp;type=pdf


J>Ну там как раз и говорится:

угу
Re[4]: Классы типов
От: Klapaucius  
Дата: 01.11.14 13:53
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Ошибка будет не при компиляции Add<float>, а при компиляции sum.


Вы будете смеяться, но неполная имплементация инстанса в хаскеле — не ошибка, а ворнинг:

Prelude> data D = D
Prelude> class C a where c :: a

==================== Tidy Core ====================
Result size of Tidy Core = {terms: 4, types: 7, coercions: 2}
-- тут сгенерировалась полиморфная функция, принимающая словарь.
c
c = \ @ a tpl -> tpl `cast` ...

-- пишем пустой инстанс:
Prelude> instance C D

-- компилятор выдает ворнинг
<interactive>:13:10: Warning:
    No explicit implementation for
      ‘c’
    In the instance declaration for ‘C D’

==================== Tidy Core ====================
Result size of Tidy Core = {terms: 5, types: 4, coercions: 3}

-- После чего генерирует функцию-заглушку, кидающую эксепшн
$cc
$cc = noMethodBindingError "<interactive>:13:10-12|c"#

-- и делает словарь с ней (когда функция класса одна - словарь это просто обернутая в newtype функция)
$fCD
$fCD = $cc `cast` ...


В главном, впрочем, вы правы.
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Re[12]: Классы типов
От: jazzer Россия Skype: enerjazzer
Дата: 01.11.14 15:04
Оценка:
Здравствуйте, Klapaucius, Вы писали:

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


J>>Ну там как раз и говорится:

J>>

J>>Haskell type classes and various extensions can be emulated in C++ by C++ templates/traits and some amount of compile-time metaprogramming. ...C++ can easily handle other possible extensions to Haskell type classes.


K>Что тут удивительного? C++ "эмулирует" средства, добавляемые в язык с параметрическим полиморфизмом для того, чтоб получить ad-hoc полиморфизм. Т.е. полиморфизм, который в С++ основной. Правильнее было бы, наверное, сказать, что это хаскель "эмулирует" C++ средства.

K>Удивительно было бы, если бы C++ не "эмулировал" то, что в нем и так есть, а — наоборот — то, чего в нем нет — т.е. параметрический полиморфизм.

А чем тебе traits не параметрический полиморфизм? Ты меня поправь, если я понимаю неправильно, но параметрический полиморфизм от ad-hoc отличается лишь тем, что в ПП реализация одна, а все типовые зависимости вынесены в тайпклассы, в то время как в ad hoc их можно применить непосредственно (специализацией/перегрузкой).
Но traits как раз и играют роль тайпклассов, позволяя сделать одну единственную реализацию ПП-функции.
Что в Хаскеле, что в С++ "единственная" реализация ПП-функции просто будет звать типозависимые дела из тайпклассов и traits, соответственно.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[13]: Классы типов
От: samius Япония http://sams-tricks.blogspot.com
Дата: 01.11.14 15:30
Оценка:
Здравствуйте, jazzer, Вы писали:

J>А чем тебе traits не параметрический полиморфизм? Ты меня поправь, если я понимаю неправильно, но параметрический полиморфизм от ad-hoc отличается лишь тем, что в ПП реализация одна, а все типовые зависимости вынесены в тайпклассы, в то время как в ad hoc их можно применить непосредственно (специализацией/перегрузкой).

J>Но traits как раз и играют роль тайпклассов, позволяя сделать одну единственную реализацию ПП-функции.
J>Что в Хаскеле, что в С++ "единственная" реализация ПП-функции просто будет звать типозависимые дела из тайпклассов и traits, соответственно.
traits и type classes это как раз ad-hoc (https://www.haskell.org/haskellwiki/Polymorphism#Ad-hoc_polymorphism).
ПП работает для любого типа. Он unconstrained. Потому, любая функция, которой нужно ограничение (traits, type classes), не может быть ПП.
Re[4]: Классы типов
От: jazzer Россия Skype: enerjazzer
Дата: 01.11.14 15:57
Оценка:
Здравствуйте, Klapaucius, Вы писали:

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


K>Ох, опять двадцать пять.


K>
K>sum :: forall a. Add a => [a] -> a
K>


K>А какая сигнатура у вашей sum?


K>
J>>template<class a>
J>>a sum(vector<a> v) {
J>>  return std::accumulate( std::begin(v), std::end(v), Add<a>::plus, Add<a>::zero() );
J>>}
K>


K>Вы ее, например, попробуйте на псевдохаскеле написать и сразу все ясно станет.


Если ты намекаешь на то, что Add должна быть в сигнатуре, то, во-первых, я тебе ее и на С++ напишу:
template<class a>
typename enable_if< CheckTypeClass<Add, a>, a >::type
sum(vector<a> v);

где CheckTypeClass проверяет, что Add<a> определен и делает то, что надо.
А во-вторых, именно этим и занимаются концепты в явном виде:
template<Add a>
a sum(vector<a> v);

использование Add вместо обобщенного class как раз и означает проверку концепта (т.е. тайпкласса).

Вариант реализации CheckTypeClass (просто проверка сигнатур plus и zero):
template<class a>
struct CheckTypeClass<Add, a>
  : and_< is_same< decltype(Add<a>::plus), a(a, a) >
        , is_same< decltype(Add<a>::zero), a() >
        >
{};


Соответственно, возвращаясь к примеру Wolfhound-а, если воткнуть проверку
static_assert(CheckTypeClass<Add,float>::value,"Add<float> is not correct");

сразу после объявления неполного Add<float> без zero, то мы мгновенно получим сообщение об ошибке:
main.cpp: In instantiation of 'struct CheckTypeClass<Add, float>':
main.cpp:34:40:   required from here
main.cpp:27:136: error: 'zero' is not a member of 'Add<float>'

до объявления sum, всё, как хотел Wolfhound.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[13]: Классы типов
От: Klapaucius  
Дата: 01.11.14 16:09
Оценка:
Здравствуйте, jazzer, Вы писали:

K>>Что тут удивительного? C++ "эмулирует" средства, добавляемые в язык с параметрическим полиморфизмом для того, чтоб получить ad-hoc полиморфизм. Т.е. полиморфизм, который в С++ основной. Правильнее было бы, наверное, сказать, что это хаскель "эмулирует" C++ средства.

K>>Удивительно было бы, если бы C++ не "эмулировал" то, что в нем и так есть, а — наоборот — то, чего в нем нет — т.е. параметрический полиморфизм.

J>Ты меня поправь, если я понимаю неправильно, но параметрический полиморфизм от ad-hoc отличается лишь тем, что в ПП реализация одна, а все типовые зависимости вынесены в тайпклассы, в то время как в ad hoc их можно применить непосредственно (специализацией/перегрузкой).


Ну все правильно. Параметрический полиморфизм — это когда один код для любых типов. Соответственно полиморфный код, типизируется, компилируется раздельно, непробиваемая абстракция, есть полиморфная рекурсия и т.д. Но нам нужно и код для каждого типа отдельный писать.
Когда код отдельный для каждого типа — это ad-hoc полиморфизм.
Не понятно только, почему "лишь"? Куда уж больше отличая-то между полиморфизмами?

Prelude Data.Monoid> let msum xs = foldr (<>) mempty xs

-- получается один код для всех типов:
==================== Simplified expression ====================
returnIO
  (: ((\ @ b $dMonoid xs -> foldr (<> $dMonoid) (mempty $dMonoid) xs)
      `cast` ...)
     ([]))


msum :: Monoid b => [b] -> b
-- это была параметрически полиморфная часть.
Prelude Data.Monoid> data D = D

-- а теперь пишем код специфический для данного типа.
Prelude Data.Monoid> instance Monoid D where D `mappend` D = D; mempty = D

==================== Tidy Core ====================
Result size of Tidy Core = {terms: 15, types: 13, coercions: 0}
-- ad-hoc для типа D
$cmappend
$cmappend = \ ds ds1 -> case ds of _ { D -> ds1 }

Rec {
-- собираем в словарь
$fMonoidD
$fMonoidD = D:Monoid D $cmappend $cmconcat
-- тут у нас дефолтная реализация
$cmconcat
$cmconcat = $dmmconcat $fMonoidD
end Rec }


J>Но traits как раз и играют роль тайпклассов, позволяя сделать одну единственную реализацию ПП-функции.


Ну и где эта единственная реализация? Будет по реализации для каждого типа.
Можно конечно и параметрический полиморфизм в C++ эмулировать, боксируя все, и делая "параметрическую" функцию, работающую со ссылками.
Но смысл "эмулировать" ad-hoc полиморфизм в C++ — где он и так всегда работает — от меня все еще ускользает.

J>Что в Хаскеле, что в С++ "единственная" реализация ПП-функции просто будет звать типозависимые дела из тайпклассов и traits, соответственно.


Ну так в хаскеле-то она единственная без кавычек. Понятно, что — при наличии разверток — при оптимизации может появится несколько специализированных функций — но в хаскеле это деталь реализации, она семантически ненаблюдаема. В C++ весь темплейтный код на наблюдаемости такой "генеративной" реализации и основан.
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Re[5]: Классы типов
От: Klapaucius  
Дата: 01.11.14 16:16
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Если ты намекаешь на то, что Add должна быть в сигнатуре, то, во-первых, я тебе ее и на С++ напишу:

J> <...>
J>сразу после объявления неполного Add<float> без zero, то мы мгновенно получим сообщение об ошибке:
J>
J>main.cpp: In instantiation of 'struct CheckTypeClass<Add, float>':
J>main.cpp:34:40:   required from here
J>main.cpp:27:136: error: 'zero' is not a member of 'Add<float>'
J>

J>до объявления sum, всё, как хотел Wolfhound.

Ну, концепты — это опциональная "проверяемая компилятором документация", без которой и так все работает. А тайпкласс — именно то, что и работает.
у вашей функции sum один параметр vector<a> v. У моей хаскельной версии на самом деле три параметра.
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Re[14]: Классы типов
От: jazzer Россия Skype: enerjazzer
Дата: 01.11.14 16:17
Оценка:
Здравствуйте, samius, Вы писали:

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


J>>А чем тебе traits не параметрический полиморфизм? Ты меня поправь, если я понимаю неправильно, но параметрический полиморфизм от ad-hoc отличается лишь тем, что в ПП реализация одна, а все типовые зависимости вынесены в тайпклассы, в то время как в ad hoc их можно применить непосредственно (специализацией/перегрузкой).

J>>Но traits как раз и играют роль тайпклассов, позволяя сделать одну единственную реализацию ПП-функции.
J>>Что в Хаскеле, что в С++ "единственная" реализация ПП-функции просто будет звать типозависимые дела из тайпклассов и traits, соответственно.
S>traits и type classes это как раз ad-hoc (https://www.haskell.org/haskellwiki/Polymorphism#Ad-hoc_polymorphism).
S>ПП работает для любого типа. Он unconstrained. Потому, любая функция, которой нужно ограничение (traits, type classes), не может быть ПП.

Во-первых, Что значит — работает? Типы ведь очень разные бывают. Мне как-то сложно представить функцию, которая будет работать абсолютно для всех типов, кроме identity (и то только для копируемых/перемещаемых типов) и констант типа примера ниже.

Во-вторых, обычные сиплюсовые шаблоны в каком-то смысле "работают" для всех типов изначально, до того, как были изобретены traits:
template<class a> byte bestArchiverEver(a) { return byte(1); }

для любого типа. unconstrained.
Или что там в статье приводят в качестве пример, map?
map :: (a -> b) -> [a] -> [b]

Ну так и в С++ он будет такой же:
template<class a, class b> list<b> map( b(a), list<a> );

Так что мне не очень понятно, когда Klapaucius говорит, что в С++ нет ПП.

Ну и в-третьих, traits, type classes — это не (только) ограничение, а, если можно так выразиться, средство натянуть сову на глобус.
Т.е. рассказать, как функции надо работать с типом, который без этого этой функции не подходил бы.
Как в примере со встроенным массивом, у которого нет методов begin/end — но их можно предоставить извне, и тогда функция std::accumulate будет работать со всем подряд. Но (судя по статье, которую ты привел) это Ad-hoc_polymorphism и есть.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[14]: Классы типов
От: jazzer Россия Skype: enerjazzer
Дата: 01.11.14 16:31
Оценка:
Здравствуйте, Klapaucius, Вы писали:

K>Не понятно только, почему "лишь"? Куда уж больше отличая-то между полиморфизмами?

Потому что пока у нас одна функция — это параметрический полиморфизм.
Как только добавили к ней перегрузку/специализацию для какого-нть типа — все, ad hoc.
По мне так деталь абсолютно несущественная, чтоб еще и специальным названием заморачиваться и следить за правильной терминологией

J>>Но traits как раз и играют роль тайпклассов, позволяя сделать одну единственную реализацию ПП-функции.

K>Ну и где эта единственная реализация? Будет по реализации для каждого типа.

В коде, естественно. Или ты про бинарник говришь? Имхо, это вообще никакого отношения к делу не имеет — как там что на бинарном уровне генерится.

K>Можно конечно и параметрический полиморфизм в C++ эмулировать, боксируя все, и делая "параметрическую" функцию, работающую со ссылками.

K>Но смысл "эмулировать" ad-hoc полиморфизм в C++ — где он и так всегда работает — от меня все еще ускользает.
Ну так и параметрический работает "из коробки", не?

J>>Что в Хаскеле, что в С++ "единственная" реализация ПП-функции просто будет звать типозависимые дела из тайпклассов и traits, соответственно.


K>Ну так в хаскеле-то она единственная без кавычек.

Где ж без кавычек? Вон у sum единственная реализация, только вот вся реальная работа вынесена в Add.
Так что если рассматривать sum как исключительно ее код — все хорошо.
А если принять во внимание Add и различия в его реализации — то сразу получится много всего.
Так что это вопрос чисто терминологический — насколько глубоко спускаться, определяя единственность реализации.
Мне вот лично кода вполне достаточно. Если тело функции определено (в тексте программы) один раз — значит, у нее единственная реализация. Что она там зовет из себя — ее личное, десятое, дело.

K>Понятно, что — при наличии разверток — при оптимизации может появится несколько специализированных функций — но в хаскеле это деталь реализации, она семантически ненаблюдаема. В C++ весь темплейтный код на наблюдаемости такой "генеративной" реализации и основан.


где? Вроде только сигнатуры проверяются же, кого колышет бинарный код?
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[6]: Классы типов
От: jazzer Россия Skype: enerjazzer
Дата: 01.11.14 16:36
Оценка:
Здравствуйте, Klapaucius, Вы писали:

K>Ну, концепты — это опциональная "проверяемая компилятором документация", без которой и так все работает. А тайпкласс — именно то, что и работает.


traits в С++ — это тоже "именно то, что и работает".
И моя Add в С++ — тоже "именно то, что и работает".
Плюс она таки в сигнатуре, как и у тебя Add в Haskell.

K>у вашей функции sum один параметр vector<a> v. У моей хаскельной версии на самом деле три параметра.


Можно раскрыть мысль про три параметра? Я вот смотрю глазами и вижу только один — [a].
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[15]: Классы типов
От: samius Япония http://sams-tricks.blogspot.com
Дата: 01.11.14 17:26
Оценка:
Здравствуйте, jazzer, Вы писали:

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


J>>>Что в Хаскеле, что в С++ "единственная" реализация ПП-функции просто будет звать типозависимые дела из тайпклассов и traits, соответственно.

S>>traits и type classes это как раз ad-hoc (https://www.haskell.org/haskellwiki/Polymorphism#Ad-hoc_polymorphism).
S>>ПП работает для любого типа. Он unconstrained. Потому, любая функция, которой нужно ограничение (traits, type classes), не может быть ПП.

J>Во-первых, Что значит — работает? Типы ведь очень разные бывают. Мне как-то сложно представить функцию, которая будет работать абсолютно для всех типов, кроме identity (и то только для копируемых/перемещаемых типов) и констант типа примера ниже.

работает — значит handle values. Может и не значит, но я употребил "работает" примерно в этом контексте.
можно еще представить функцию length, которая возвращает длину списка для списка с любым типом элемента списка. А если напрячься, то еще и : (cons)...

J>Во-вторых, обычные сиплюсовые шаблоны в каком-то смысле "работают" для всех типов изначально, до того, как были изобретены traits:

Некоторые шаблоны работали для всех, а какие-то за счет перегрузок. Т.е. еще не traits, но уже ad-hoc
J>
J>template<class a> byte bestArchiverEver(a) { return byte(1); }
J>

J>для любого типа. unconstrained.
а мне кажется что a должен уметь передаваться по значению.

J>Или что там в статье приводят в качестве пример, map?
map :: (a -> b) -> [a] -> [b]

J>Ну так и в С++ он будет такой же:
template<class a, class b> list<b> map( b(a), list<a> );

J>Так что мне не очень понятно, когда Klapaucius говорит, что в С++ нет ПП.
На самом деле у этого map есть неявный констрейнт на тип b, который накладывает list, в том числе при добавлении элемента.

J>Ну и в-третьих, traits, type classes — это не (только) ограничение, а, если можно так выразиться, средство натянуть сову на глобус.

J>Т.е. рассказать, как функции надо работать с типом, который без этого этой функции не подходил бы.
J>Как в примере со встроенным массивом, у которого нет методов begin/end — но их можно предоставить извне, и тогда функция std::accumulate будет работать со всем подряд. Но (судя по статье, которую ты привел) это Ad-hoc_polymorphism и есть.
Согласен. Ограничение (constraint) как средство. И даже как цель.
Re[15]: Классы типов
От: Klapaucius  
Дата: 01.11.14 20:13
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Потому что пока у нас одна функция — это параметрический полиморфизм.

J>Как только добавили к ней перегрузку/специализацию для какого-нть типа — все, ad hoc.

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

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


Ну это типичный прием в таких разговорах. Регулярно на каком то этапе оказывается, что между чем угодно и чем угодно разницы нет, а значит если в C++ что-то есть, то есть и что угодно другое.
Если для вас нет разницы между параметрическим полиморфизмом и ad-hoc, то о чем вы вообще спорите? Какой-то полиморфизм в C++ есть — значит все в порядке. Какой — не важно.

J>В коде, естественно.


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

J>Или ты про бинарник говришь?


Раздельная компиляция — это только ожидаемое следствие раздельной типизации. Впрочем, у плюсовых шаблонов есть генеративные родственники, которые тоже отдельно не компилируются, зато типизируются: параметризованные модули в sml и inline-функции в F#.

J>Имхо, это вообще никакого отношения к делу не имеет — как там что на бинарном уровне генерится.


И типизируемость и раздельная компиляция как раз имеют отношение к делу. Нет никакой пользы от модели "параметрический полиморфизм", если мы к ней прибавляем: "но ничего из того, что вы ожидаете от параметрического полиморфизма не работает".

J>Ну так и параметрический работает "из коробки", не?


Нет, не работает. Его нет.

JK>>Ну так в хаскеле-то она единственная без кавычек.

J>Где ж без кавычек? Вон у sum единственная реализация, только вот вся реальная работа вынесена в Add.

Вовсе нет. Тот код, который обходит список, весь параметрически полиморфный. Чем это не "реальная работа", по сравнению со сложением?

J>Так что если рассматривать sum как исключительно ее код — все хорошо.

J>А если принять во внимание Add и различия в его реализации — то сразу получится много всего.

Ну так все хорошо, потому что в хаскеле мы можем рассматривать sum и Add раздельно. В C++ с другой стороны sum без Add — это нетипизированный и некомпилируемый код.

J>Так что это вопрос чисто терминологический — насколько глубоко спускаться, определяя единственность реализации.


Дело тут не в глубине спуска.

J>Мне вот лично кода вполне достаточно. Если тело функции определено (в тексте программы) один раз — значит, у нее единственная реализация. Что она там зовет из себя — ее личное, десятое, дело.


Ну а мне кода, который ни типизировать, ни скомпилировать, да и понять как следует нельзя — недостаточно.

J>где? Вроде только сигнатуры проверяются же, кого колышет бинарный код?


Сигнатуры не проверяются, пока вы собственноручно проверку сигнатур не напишете. Что характерно, в таких спорах я еще не разу не видел такого, чтоб проверку сразу написали, хотя все "упражнение" в общем то в ней и заключается. От опциональной типизации пользы примерно столько же, сколько от отсутствующей. Вся полезность от тайпчека как легковесной верификации — от обязательности.
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Re[7]: Классы типов
От: Klapaucius  
Дата: 01.11.14 20:27
Оценка:
Здравствуйте, jazzer, Вы писали:

K>>Ну, концепты — это опциональная "проверяемая компилятором документация", без которой и так все работает. А тайпкласс — именно то, что и работает.


J>traits в С++ — это тоже "именно то, что и работает".

J>И моя Add в С++ — тоже "именно то, что и работает".
J>Плюс она таки в сигнатуре, как и у тебя Add в Haskell.

Нет, это не то, что работает. Это ненужные приседания. В темплейтной функции суммирования можно + писать без всяких передач словарей. Раздельной типизации и компиляции, которые мы и оплачиваем этими "приседаниями" в хаскеле — в плюсах все равно нет.

K>>у вашей функции sum один параметр vector<a> v. У моей хаскельной версии на самом деле три параметра.


J>Можно раскрыть мысль про три параметра? Я вот смотрю глазами и вижу только один — [a].


Не знаю, куда вы смотрите. Посмотрите в код в моих сообщениях, там все параметры отлично видны.
Могу повторить код с типами, которые я совершенно напрасно отфильтровал в прошлый раз:
Prelude Data.Monoid> let msum xs = foldr (<>) mempty xs

==================== Simplified expression ====================
returnIO  -- на эти навороты можно внимания не обращать
  @ [()]  -- это из-за объявления в интерпретаторе
  (: @ () -- рассахаренная функция - лямбда ниже
     ((\ (@ b) ($dMonoid :: Monoid b) (xs :: [b]) ->
         foldr @ b @ b (<> @ b $dMonoid) (mempty @ b $dMonoid) xs)
      `cast` ...)
     ([] @ ())) 

-- сюда я явно параметр дописал, сейчас - думаю - будет понятнее.
msum :: forall a. Monoid b => [b] -> b

Prelude Data.Monoid> instance Monoid D where D `mappend` D = D; mempty = D

==================== Tidy Core ====================
Result size of Tidy Core = {terms: 15, types: 13, coercions: 0}

$cmappend :: D -> D -> D
$cmappend = \ (ds :: D) (ds1 :: D) -> case ds of _ { D -> ds1 }

Rec {
$fMonoidD :: Monoid D
$fMonoidD = D:Monoid @ D D $cmappend $cmconcat

$cmconcat :: [D] -> D
$cmconcat = $dmmconcat @ D $fMonoidD
end Rec }
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.