Давече господину Воронкову Василию был задан вопрос, зачем нужен динамик.
Что бы возвращать разные типы из функции в записимости от входящих параметров, отвечает он.
def foo(x): if x == 0 then 0 else "bar" end
Я предлагаю статически типизированое решение, что то похожее на
let foo x = if x == 0 then 0 else "bar" end
foo :: int -> int | string
На что он делает два утверждения
а) действительно разобраться в том, что такое "алгебраический тип" и почему приведенный вами код никакого к ним отношения не имеет.
б) почитать о том, что такое система типов и почему приведенный вами код является классическим (см. того же Пирса) примером кода, который не пропустит любая система типов.
Насколько я понимаю, до сих пор эти высказывания в силе.
Интересует достоверность высказывания б). Может ли кто объяснить не ссылаясь на священые писания почему это так. Я умных книжек не читал поэтому совершено не вижу в чем тут может быть проблема, какая разница один тип или несколько, плюс мне видится это это вполне реализуемое как сахар поверх какого нибудь
type IntString = X of int | Y of string
Так же можно обсудить, общую здравость идеи зависимости сигнатуры функции от входящих параметров.
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Talk is cheap. Show me the code.
Re: [Динамик не нужен] Анонимные алгебраические типы.
D>Давече господину Воронкову Василию был задан вопрос, зачем нужен динамик. D>Что бы возвращать разные типы из функции в записимости от входящих параметров, отвечает он. D>
D>def foo(x): if x == 0 then 0 else "bar" end
D>
D>Я предлагаю статически типизированое решение, что то похожее на D>
D>let foo x = if x == 0 then 0 else "bar" end
D>foo :: int -> int | string
D>
D>На что он делает два утверждения D>а) действительно разобраться в том, что такое "алгебраический тип" и почему приведенный вами код никакого к ним отношения не имеет. D>б) почитать о том, что такое система типов и почему приведенный вами код является классическим (см. того же Пирса) примером кода, который не пропустит любая система типов.
D>Насколько я понимаю, до сих пор эти высказывания в силе. D>Интересует достоверность высказывания б). Может ли кто объяснить не ссылаясь на священые писания почему это так. Я умных книжек не читал поэтому совершено не вижу в чем тут может быть проблема, какая разница один тип или несколько, плюс мне видится это это вполне реализуемое как сахар поверх какого нибудь D>
D>type IntString = X of int | Y of string
D>
Чёрт знает насчёт теоретически возможного, но в текущих языках с АТД (Haskell, Ocaml) такой фокус не прокатит, потому что вызывающая функция должна явно "распаковывать" строковое или численное значение из типа IntString с помощью матчинга на один из конструкторов. Кроме того, по крайней мере в хацкеле, внутри модуля конструкторы уникальны.
То есть type IntString объявить действительно несложно и объявить функцию, которая его возвращает, даже неявно — несложно. А вот как вы себе представляете использование такой функции?
D>Так же можно обсудить, общую здравость идеи зависимости сигнатуры функции от входящих параметров.
Это у кого куда мозг повёрнут. Любители динамики совершенно спокойно мыслят функциями, которые утром возвращают строку, а вечером boolean; любители статики от такого делят на ноль и начинают собирать аргументы против. Мой посыл заключается в том, что здравость (любой) идеи всегда будет оценена субъективно, то есть обсуждение скатится в срач — оно вам надо?
Чтобы не для срача, а конструктивно, нужно выбрать точку отсчёта (например, такая зависимость нам не нужна, а когда другие её используют мы будем делать так-то и так-то) и/или критерий оценки (например, сложность реализации компилятора, который подобное схавает).
Если для срача, то идея бредовая. Функции должны иметь постоянную сигнатуру. Навскидку не припомню, чтобы понадобилось обратное.
Re[2]: [Динамик не нужен] Анонимные алгебраические типы.
Здравствуйте, Temoto, Вы писали:
T>Чёрт знает насчёт теоретически возможного, но в текущих языках с АТД (Haskell, Ocaml) такой фокус не прокатит, потому что вызывающая функция должна явно "распаковывать" строковое или численное значение из типа IntString с помощью матчинга на один из конструкторов. Кроме того, по крайней мере в хацкеле, внутри модуля конструкторы уникальны.
T>То есть type IntString объявить действительно несложно и объявить функцию, которая его возвращает, даже неявно — несложно. А вот как вы себе представляете использование такой функции?
Матчинг будет не по конструктору а по типу
let x =
match x with
| :? Int as y -> print "is int"
| :? String as y -> print "is string"
D>>Так же можно обсудить, общую здравость идеи зависимости сигнатуры функции от входящих параметров.
T>Это у кого куда мозг повёрнут. Любители динамики совершенно спокойно мыслят функциями, которые утром возвращают строку, а вечером boolean; любители статики от такого делят на ноль и начинают собирать аргументы против. Мой посыл заключается в том, что здравость (любой) идеи всегда будет оценена субъективно, то есть обсуждение скатится в срач — оно вам надо?
Кто же спорит, кто то любит биться головой об стену, кто то нет. За объективность всегда можно взять мнение большенства, конечно учитывая что большенство может при этом быть не правым.
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Talk is cheap. Show me the code.
Re: [Динамик не нужен] Анонимные алгебраические типы.
open Printf
let foo x =
if x = 0 then `MyInt 0 else `MyStr "bar"let print = function
| `MyInt x -> printf "`MyInt = %d\n" x
| `MyStr x -> printf "`MyStr = %s\n" x
| `MyFloat x -> printf "`MyStr = %f\n" x
let _ = print (foo 0)
let _ = print (foo 1)
Здравствуйте, dotneter, Вы писали:
D>Давече господину Воронкову Василию был задан вопрос, зачем нужен динамик. D>Что бы возвращать разные типы из функции в записимости от входящих параметров, отвечает он.
Весьма сомнительно желание.
D>а) действительно разобраться в том, что такое "алгебраический тип" и почему приведенный вами код никакого к ним отношения не имеет. D>б) почитать о том, что такое система типов и почему приведенный вами код является классическим (см. того же Пирса) примером кода, который не пропустит любая система типов.
Гонит по обоим пунктам.
D>плюс мне видится это это вполне реализуемое как сахар поверх какого нибудь
Вполне себе вариант.
правда и сигнатуру функции тогда уж описывать так
foo :: int -> X int | Y string
let foo x = if x == 0 then X 0 else Y "bar" end
Ибо вот это:
let x =
match x with
| :? Int as y -> print "is int"
| :? String as y -> print "is string"
Мне определенно не нравится.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re: [Динамик не нужен] Анонимные алгебраические типы.
Здравствуйте, WolfHound, Вы писали:
WH>Вполне себе вариант. WH>правда и сигнатуру функции тогда уж описывать так WH>
WH>foo :: int -> X int | Y string
WH>let foo x = if x == 0 then X 0 else Y "bar" end
WH>
WH>Ибо вот это: WH>
WH>let x =
WH> match x with
WH> | :? Int as y -> print "is int"
WH> | :? String as y -> print "is string"
WH>
WH>Мне определенно не нравится.
Чем оно сильно хуже кортежа? У того несколько позиций, у этого одна с несколькими типами. Мне как раз видется
(int | string)
(int , string)
неким подобием замкнутого базиса.
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Talk is cheap. Show me the code.
Re[3]: [Динамик не нужен] Анонимные алгебраические типы.
D>Это как раз и есть обобщеный IntString, вопрос можно ли убрать у D>data Either a b = Left a | Right b D>все имена оставив только a | b
Ну, отдавая себе отчёт в том, что для дальнейшей унифицированной работы с получившимся хозяйством нужна (упорядоченная) пара функций (a->c)*(b->c), почему бы нет?
Re[3]: [Динамик не нужен] Анонимные алгебраические типы.
T>>Чёрт знает насчёт теоретически возможного, но в текущих языках с АТД (Haskell, Ocaml) такой фокус не прокатит, потому что вызывающая функция должна явно "распаковывать" строковое или численное значение из типа IntString с помощью матчинга на один из конструкторов. Кроме того, по крайней мере в хацкеле, внутри модуля конструкторы уникальны.
T>>То есть type IntString объявить действительно несложно и объявить функцию, которая его возвращает, даже неявно — несложно. А вот как вы себе представляете использование такой функции?
D>Матчинг будет не по конструктору а по типу
D>
D>let x =
D> match x with
D> | :? Int as y -> print "is int"
D> | :? String as y -> print "is string"
D>
Если матчинг обязательный явный, то оно есть уже сегодня, если конструкторы будут названы так же: Int и String. Но я не думаю, что анонимность конструкторов тут самая большая беда. Чтобы воспользоваться значением, его всё-таки придётся из алгебраического типа распаковать — вот что самое неудобное. В динамике "оно само", без лишних switch/match.
Re[4]: [Динамик не нужен] Анонимные алгебраические типы.
T>Если матчинг обязательный явный, то оно есть уже сегодня, если конструкторы будут названы так же: Int и String. Но я не думаю, что анонимность конструкторов тут самая большая беда. Чтобы воспользоваться значением, его всё-таки придётся из алгебраического типа распаковать — вот что самое неудобное. В динамике "оно само", без лишних switch/match.
Ну в этом суть статики, нужно переодически подсказывать компилятору что да как, что бы избежать ряда проблем.
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Talk is cheap. Show me the code.
Re: [Динамик не нужен] Анонимные алгебраические типы.
Здравствуйте, dotneter, Вы писали:
D>Давече господину Воронкову Василию был задан вопрос, зачем нужен динамик. D>Что бы возвращать разные типы из функции в записимости от входящих параметров, отвечает он. D>
D>def foo(x): if x == 0 then 0 else "bar" end
D>
И что? Даже в динамических языках функции возвращают значения одного и того же типа -- вариантного да, но не изменяемого значениями входных аргументов. foo *не возвращает* разные типы -- она возвращает один тип, просто этот тип допускает строковые и числовые значения.
Вопрос в том -- надо ли нам ограничивать типы насколько возможно (статический случай) или отпустить их насколько возможно (динамические языки). И тут я вижу два аргумента.
Один -- низкоуровневый, для С и подобных.
Сигнатура функции и типы её входных данных -- важная помощь компилятору в оптимизации. Сравните:
int f(int x);
void *f(void *x);
В первом случае значение x может пройти в регистре, компилятор может не включать анализ косвенности при межпроцедурной оптимизации, функция лучше инлайнится, возвращаемое значение не требует разыменования и у нас меньше косвенных адресаций при выполнении.
Второй -- высокоуровневый.
В таких языках как Haskell эта помощь становится не только помощью компилятору в производительности, но и помощью программисту в формировании абстракции. Рассмотрим пример вашего оппонента -- имея такую функцию ему придётся городить в коде рантаймовую проверку типа, который реально вернула foo на вызове foo(i), и есть шанс забыть, совершить ошибку, использовать не то значение и т.п. в Haskell же достаточно написать Either и сматчить Left / Right, как было показано выше по ветке -- и даже это уже во-первых произойдёт на компиляции во-вторых убережёт от кучи ошибок, в третьих сократит код.
Re: [Динамик не нужен] Анонимные алгебраические типы.
Тогда уж и такой полиморфизм изобразить можно было бы :
let foo x = if x == 0 then 0 else "hi" end
foo :: int -> int | string
let bar i = i + 1
let bar s = s + "\n"
let x1 = foo 0
x1 :: int | string
let x2 = foo 1
x2 :: int | string
//Магия:
let z1 = bar x1
z1 :: int | string
let z2 = bar x2
z2 :: int | string
Re[2]: [Динамик не нужен] Анонимные алгебраические типы.
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, deniok, Вы писали:
D>>Зачем себя ограничивать ad hoc полиморфизмом, когда можно определить параметрически D>>
D>>mapSum :: (a -> c) -> (b -> d) -> a | b -> c | d
D>>
WH>Плохая идея. WH>Что будешь делать если понадобиться маписать объедение 3х типов? Еще одну функцию писать?