Re[11]: Что должен возвращать if?
От: gbear Россия  
Дата: 27.10.14 10:59
Оценка:
Здравствуйте, Sinclair, Вы писали:

G>>Почему только при присвоении?! Везде, где "по смыслу" должно быть T.

S>Везде, где по смыслу должно быть T, должен быть лифтинг.
S>Монада — она на то и монада.

Так-то да. Но, там речь даже не о типо-maybe шла... А о неком variant[T], который не монада, а есть "упращение" от variant[T, U] при U = T. В это предлагается вычислять if-с-else.

---
С уважением, Константин Сиваков
Re[7]: Nemerle через 5 лет - выстрелит или скончается?
От: gbear Россия  
Дата: 27.10.14 11:07
Оценка: 4 (1) +1
Здравствуйте, Sinclair, Вы писали:

S>А зачем вы обязательно хотите одинаковости в вычислениях if-с-else и if-без-else?

S>На мой взгляд, это два разных оператора, которые вполне имеют право возвращать разные результаты.

Я-то как раз никакой одинаковости и не "хочу". Это действительно два разных оператора, и то, что в сабже у них и синтаксис разный — это даже плюс, имхо.

S>Можно вообще считать else шорткатом для оператора ??.

S>То есть результат выражения if (x == 5) 42 имеет тип Nullable<int>.
S>Результат выражения if (x == 5) 42 else 41 имеет тот же тип, что и someNullableInt ?? 41, т.е. просто int.

Соглашусь, только если не Nullable<int>, а честный maybe<int>. Nullable, в этом случае, такой же паллиатив как и variant[int, void]

---
С уважением, Константин Сиваков
Re[16]: Nemerle через 5 лет - выстрелит или скончается?
От: Evgeny.Panasyuk Россия  
Дата: 27.10.14 11:20
Оценка:
Здравствуйте, gbear, Вы писали:

G>Вот, при вычислении мы получили некий variant[int, void]. Вы, только честно, способны сказать _что_ мы получили? Ваше типо-maybe? Или, может быть, это "нормальный" variant?


А чем он не нормальный?

G>Вы предлагаете интерпритировать _любой_ variant[T, void] как maybe чтоли?! А если T — внезапно — окажется void? if(x > 0) foo(x) — это тогда "go wrong" — без вариантов


Почему go wrong? После упрощения будет просто void.
Если же хочется большой verbose многоэтажности, то можно делать: variant[just[T], nothing], для нескольких веток — variant[just[T], just[U], nothing] (или как вариант — variant[variant[T, U], nothing]), если есть else — то убрать nothing.

G>А что делать в "обобщенном коде", когда любой variant[T, U], при таком подходе, способен внезапно стать таким типо-maybe?

G>Еще раз... maybe — вещь вполне конкретная. Обладает вполне определенной семантикой. variant — такой семантической нагрузки не несет. И "усилием воли" её на него "повесить" не выйдет.

Допустим что у maybe есть какая-то специальная maybe-семантика, которая с variant'ом не вяжется ну никак. Ок, просто не будем называть Variant[T, void] maybe — делов-то

G>>>Есть foo(x) -> void и bar(x) -> variant[int, void].

G>>>
G>>>if(x > 0) bar(x) else foo(x)
G>>>

G>>>Нужно "дергать"?
EP>>Если неявного упрощения нет — то да, можно.
G>Кхм... я дико извиняюсь. Но я таки спрашивал вас не за "можно", а за "нужно".

Нужно или нет зависит от конкретной ситуации. Вполне возможно что в обобщённом коде понадобится не упрощённая версия:
auto first = bar(1);
// ...
auto v = if(x > 0) bar(2) else foo(x);
match(v) case(v is typeof(bar(1))) { first = v; } // ...

В то же время можно представить ситуацию, когда нужна именно упрощённая версия — например return simplify(if(x > 0) bar(2) else foo(x));.
Именно поэтому "можно", а не "нужно".
Re: Что должен возвращать if?
От: Klapaucius  
Дата: 27.10.14 14:19
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>А почему void, а не Maybe?


Тогда уж if без else должен возвращать Alternative f => f a, а уж никак не Maybe.
Но в nemerle нет higher-kinded polymorphism, поэтому сделать так нельзя.
Версия с void вполне имеет право на существование, у нее другие юзкейсы, в том же хаскеле (теперь) есть
guard :: Alternative f => Bool -> f ()
when :: Applicative f => Bool -> f () -> f ()
unless :: Applicative f => Bool -> f () -> f ()

Правда, в хаскеле when более общая функция, чем guard, про обсуждаемую "версию с void" такого не скажешь.
(до AMP вместо Alternative был MonadPlus, а вместо Applicative — Monad, в контексте разговора это не интересно, Monad для такой функции не требуется, а MonadPlus исключительно продукт недоделанности хаскельной библиотеки, который в других языках повторять не нужно)
'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[10]: Что должен возвращать if?
От: Sinclair Россия https://github.com/evilguest/
Дата: 27.10.14 19:05
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Опять же, это можно делать одним явным вызовов унарного оператора, который по-максимуму упростит тип.
Этот унарный оператор нужно будет постоянно втыкать к месту и не к месту.
Зачем он нужен? У нас есть реальная потребность оперировать вложенными вариантами?

EP>Основной вопрос в том, сколько неявности можно себе позволить, не сломав при этом обобщённый код (в который могут прийти и типы приводящие к variant'у который можно упростить и те для которых его упростить нельзя).

Я пока затрудняюсь представить себе такой сценарий, в котором обобщённый код сломается из-за автоупрощения. Вы можете представить себе такой код?

EP>Опять таки, возникает вопрос совместимости с обобщённым кодом: if(x == 5) T() else U() — тут T и U могут быть одинаковые или разные.

Ну да. Если T и U одинаковые, то в одном из вариантов языка мы имеем T благодаря автоупрощению, в другом — Object, если нет ограничений на T и U.

Ну или C, если в декларации параметров T и U указано where T:C, U:C.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[12]: Что должен возвращать if?
От: Sinclair Россия https://github.com/evilguest/
Дата: 27.10.14 19:06
Оценка:
Здравствуйте, gbear, Вы писали:
G>Так-то да. Но, там речь даже не о типо-maybe шла... А о неком variant[T], который не монада, а есть "упращение" от variant[T, U] при U = T. В это предлагается вычислять if-с-else.
Упрощением от variant<T, U> для T=U должен быть просто T.
Потому что "int или int" — это просто int.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Что должен возвращать if?
От: VladD2 Российская Империя www.nemerle.org
Дата: 28.10.14 00:16
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>А почему void, а не Maybe?


Потому что Maybe тут никому не нужен. Еще потому что внутри when может быть return/break/continue/возврат из именованного блока. Ну, и с точки зрения производительности выделение памяти под Maybe не комильфо. Кому надо заманадить, может воспользоваться комьютейшон экспрешонами, где все можно определить так как хочется.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[16]: Что должен возвращать if?
От: Sinclair Россия https://github.com/evilguest/
Дата: 28.10.14 06:08
Оценка:
Здравствуйте, gbear, Вы писали:
G>Вот, при вычислении мы получили некий variant[int, void]. Вы, только честно, способны сказать _что_ мы получили? Ваше типо-maybe? Или, может быть, это "нормальный" variant?
G>Вы предлагаете интерпритировать _любой_ variant[T, void] как maybe чтоли?! А если T — внезапно — окажется void? if(x > 0) foo(x) — это тогда "go wrong" — без вариантов
Упрощение variant[T, T] должно давать T для любого T. В том числе и для void. Так что (if(x > 0) foo(x)) будет иметь тип void, что вполне совпадает с интуитивными ожиданиями.

G>А что делать в "обобщенном коде", когда любой variant[T, U], при таком подходе, способен внезапно стать таким типо-maybe?

А в чём тут проблема, напомните?

G>Еще раз... maybe — вещь вполне конкретная. Обладает вполне определенной семантикой. variant — такой семантической нагрузки не несет. И "усилием воли" её на него "повесить" не выйдет.

Я вижу у maybe только одно отличие от абстрактного варианта — это наличие доп. синтаксиса с hasValue.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[13]: Что должен возвращать if?
От: jazzer Россия Skype: enerjazzer
Дата: 28.10.14 06:30
Оценка: 66 (1)
Здравствуйте, Sinclair, Вы писали:

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

G>>Так-то да. Но, там речь даже не о типо-maybe шла... А о неком variant[T], который не монада, а есть "упращение" от variant[T, U] при U = T. В это предлагается вычислять if-с-else.
S>Упрощением от variant<T, U> для T=U должен быть просто T.
S>Потому что "int или int" — это просто int.

Позволю себе еще раз указать на имеющуюся уже практику в определении типа атрибутов грамматик в Spirit 2:
Раз: http://rsdn.ru/forum/philosophy/5823411.1
Автор: jazzer
Дата: 18.10.14

Два: http://www.boost.org/doc/libs/1_56_0/libs/spirit/doc/html/spirit/qi/quick_reference/compound_attribute_rules.html

В "два" как раз есть случай помянутого выше упрощения для альтернативного парсера a | b (т.е. if/else по сути):
a: A, b: B --> (a | b): variant<A, B>
a: A, b: Unused --> (a | b): optional<A>
a: A, b: B, c: Unused --> (a | b | c): optional<variant<A, B> >
a: Unused, b: B --> (a | b): optional<B>
a: Unused, b: Unused --> (a | b): Unused
a: A, b: A --> (a | b): A

тут a, b — это выражения (парсеры), а A, B — их типы (типы их атрибутов), optional — это Maybe, Unused — void.

Для опционального парсера -a (т.е. if без else):
a: A --> -a: optional<A>
a: Unused --> -a: Unused


Так что все уже придумано и работает.
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[17]: Что должен возвращать if?
От: Klapaucius  
Дата: 28.10.14 13:22
Оценка: +1
Здравствуйте, Sinclair, Вы писали:

S>Упрощение variant[T, T] должно давать T для любого T. В том числе и для void. Так что (if(x > 0) foo(x)) будет иметь тип void, что вполне совпадает с интуитивными ожиданиями.


В этом разговоре как-то смешиваются типы-объединения с типами-суммами. Да T V T — это то же самое, что и T. Но T + T — не то же самое, что T.
Упрощенно говоря T + T = Left * T V Right * T, мы всегда можем отличить значение производимое injl от injr по "тегу".
Суммы, они же алгебраические типы и "варианты" — вещь распространенная, полезная на практике. Объединения, с другой стороны, штука довольно сомнительная и редко встречающаяся.

Что из себя представляет boost variant я вообще не смогу навскидку сказать, к примеру, он описывается как "set of types", и "static visitor" различает элементы по типу. Т.е. это никакой не вариант (не тип-сумма). Но с другой стороны это и не объединение, потому что мы не можем просто применять к значению этого типа функции, определенные на всех его элементах без приседаний со всякими визиторами. Т.е. он, похоже, совмещает в себе недостатки сумм и объединений (не могу сказать, что это неожиданный итог, раз уж речь идет о какой-то C++-поделке).

Действительно, с помощью объединений можно типизировать if таким образом:
Γ |- t1 : T1, T1 = Bool, Γ |- t2 : T2, Г |- t3 : T3, T2 V T3 = T
----------------------------------------------------------------
Γ |- if t1 then t2 else t3 : T

а if без else как T2 V Unit, но это полностью бессмысленно, потому что на объединении безопасны только операции, которые определены на всех элементах объединения, а на Unit (который тут void называют) ничего интересного не определить. Т.е. никакой практической разницы с возвращением просто Unit нет.
Сумму же можно элиминировать паттерн-матчингом (благодаря тегам) и обработать каждый элемент суммы теми операциями, которые на этом элементе определены.

G>>А что делать в "обобщенном коде", когда любой variant[T, U], при таком подходе, способен внезапно стать таким типо-maybe?

S>А в чём тут проблема, напомните?

S>Я вижу у maybe только одно отличие от абстрактного варианта — это наличие доп. синтаксиса с hasValue.


Не понял, что за синтаксис. Maybe T — это сумма типа T и единицы.
То, что тут проходит под названием "типа Maybe" — это Alternative.
Если обобщеный "if без else" типизировать как Alternative f => Bool -> a -> f a то он будет работать с любым "типа Maybe", хоть с Maybe, хоть со списком, хоть с суммой типа с чем-то являющимся моноидом, т.е. в том числе и для суммы типа с единицей — Either () a.
Полиморфизм тут облегчает дизайнерское решение с выборами конкретного "типа Maybe" просто устраняя необходимость выбора: все что работает как Maybe будет работать с таким "if без else"
'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...
Пока на собственное сообщение не было ответов, его можно удалить.