Структурная и номанативная типизация
От: x-code  
Дата: 18.04.11 06:10
Оценка:
Похожая тема уже была здесь
Автор: VladD2
Дата: 06.03.11
, но меня интересует нечто другое.
Возможно одновременное существование структурной и номинативной типизации в обычном си-подобном языке программирования? Как можно оформить это синтаксически — чтобы было красиво и понятно?
Для примера — вариант в Scala:
class File(name: String) {
  def getName(): String = name
  def open() { /*..*/ }
  def close() { println("close file") }
}
def test(f: { def getName(): String }) { println(f.getName) }

test(new File("test.txt"))
test(new java.io.File("test.txt"))

В Go вроде бы тоже есть нечто подобное, но не нашел примера
А можно сделать еще лучше? При этом (важно!) не ломая классического синтаксиса обычной номинативной типизации ?
Re: Структурная и номанативная типизация
От: night beast СССР  
Дата: 18.04.11 06:35
Оценка:
Здравствуйте, x-code, Вы писали:

XC>Похожая тема уже была здесь
Автор: VladD2
Дата: 06.03.11
, но меня интересует нечто другое.

XC>Возможно одновременное существование структурной и номинативной типизации в обычном си-подобном языке программирования? Как можно оформить это синтаксически — чтобы было красиво и понятно?
XC>Для примера — вариант в Scala:
XC>
XC>class File(name: String) {
XC>  def getName(): String = name
XC>  def open() { /*..*/ }
XC>  def close() { println("close file") }
XC>}
XC>def test(f: { def getName(): String }) { println(f.getName) }

XC>test(new File("test.txt"))
XC>test(new java.io.File("test.txt"))
XC>


prototype getName {};

def test[getName,...] {
   /*...*/
};
Re: Структурная и номанативная типизация
От: dotneter  
Дата: 18.04.11 06:43
Оценка:
Здравствуйте, x-code, Вы писали:

XC>Похожая тема уже была здесь
Автор: VladD2
Дата: 06.03.11
, но меня интересует нечто другое.

XC>Возможно одновременное существование структурной и номинативной типизации в обычном си-подобном языке программирования? Как можно оформить это синтаксически — чтобы было красиво и понятно?
XC>Для примера — вариант в Scala:
XC>
XC>class File(name: String) {
XC>  def getName(): String = name
XC>  def open() { /*..*/ }
XC>  def close() { println("close file") }
XC>}
XC>def test(f: { def getName(): String }) { println(f.getName) }

XC>test(new File("test.txt"))
XC>test(new java.io.File("test.txt"))
XC>

XC>В Go вроде бы тоже есть нечто подобное, но не нашел примера
XC>А можно сделать еще лучше? При этом (важно!) не ломая классического синтаксиса обычной номинативной типизации ?

def test(f: auto) { println(f.getName) }
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Talk is cheap. Show me the code.
Re: Структурная и номанативная типизация
От: jazzer Россия Skype: enerjazzer
Дата: 18.04.11 06:49
Оценка:
Здравствуйте, x-code, Вы писали:

XC>Возможно одновременное существование структурной и номинативной типизации в обычном си-подобном языке программирования? Как можно оформить это синтаксически — чтобы было красиво и понятно?

XC>
XC>def test(f: { def getName(): String }) { println(f.getName) }

XC>


шаблоны в С++:
void test(T f)
{
  BOOST_MPL_ASSERT((is_same< decltype(f.getName()), string >));
  cout << f.getName();
}

это если нужно просто отвалиться по assert в случае неправильного типа.

Если же хочется перегрузки по наличию/отсутствию функции, то нужно будет эту проверку упаковать в enable_if:
template<class T>
auto test(T f) -> typename enable_if<
                    is_same< decltype(f.getName()), string >
                  >::type
{
  cout << f.getName();
}
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[2]: Структурная и номанативная типизация
От: x-code  
Дата: 18.04.11 07:17
Оценка: +1
Здравствуйте, jazzer, Вы писали:

J>шаблоны в С++:

J>
J>void test(T f)
J>{
J>  BOOST_MPL_ASSERT((is_same< decltype(f.getName()), string >));
J>  cout << f.getName();
J>}
J>

J>это если нужно просто отвалиться по assert в случае неправильного типа.

J>Если же хочется перегрузки по наличию/отсутствию функции, то нужно будет эту проверку упаковать в enable_if:

J>
J>template<class T>
J>auto test(T f) -> typename enable_if<
J>                    is_same< decltype(f.getName()), string >
                  >>::type
J>{
J>  cout << f.getName();
J>}
J>


Кстати, интерсный пример для иллюстрации цели этой темы. Я программист С++, почти ничего не понял в этом коде при этом на Скале не писал ни строчки кода вообще, а пример вполне понятен.
Re: Структурная и номанативная типизация
От: Temoto  
Дата: 18.04.11 07:20
Оценка:
XC>Похожая тема уже была здесь
Автор: VladD2
Дата: 06.03.11
, но меня интересует нечто другое.

XC>Возможно одновременное существование структурной и номинативной типизации в обычном си-подобном языке программирования? Как можно оформить это синтаксически — чтобы было красиво и понятно?
XC>Для примера — вариант в Scala:
XC>
XC>class File(name: String) {
XC>  def getName(): String = name
XC>  def open() { /*..*/ }
XC>  def close() { println("close file") }
XC>}
XC>def test(f: { def getName(): String }) { println(f.getName) }

XC>test(new File("test.txt"))
XC>test(new java.io.File("test.txt"))
XC>

XC>В Go вроде бы тоже есть нечто подобное, но не нашел примера

package main

import "fmt"

type File struct {}
func (f File) getName() string {
  return "John"
}

func test(f interface{getName() string}) string {
  return f.getName()
}

func main() {
        var f File
    fmt.Println("Hello", test(f))
}


XC>А можно сделать еще лучше? При этом (важно!) не ломая классического синтаксиса обычной номинативной типизации ?



def test(f: auto) { println(f.getName) }
Re: Структурная и номанативная типизация
От: Sorc17 Россия  
Дата: 18.04.11 07:30
Оценка:
Ни скалы ни С++ не знаю, напишите пример для особо одарённых Java программистов пожалуйста
Для нас [Thompson, Rob Pike, Robert Griesemer] это было просто исследование. Мы собрались вместе и решили, что ненавидим C++ [смех].
Re[3]: Структурная и номанативная типизация
От: jazzer Россия Skype: enerjazzer
Дата: 18.04.11 07:30
Оценка:
Здравствуйте, x-code, Вы писали:

XC>Кстати, интерсный пример для иллюстрации цели этой темы. Я программист С++, почти ничего не понял в этом коде

В "этом коде" — это во втором? Ну так для этого надо быть в теме enable_if (http://www.boost.org/libs/utility/enable_if.html), это да, тут ничего не поделаешь. Но это нужно только если нужна перегрузка — не самый частый случай, обычно просто сообщения об ошибке достаточно, и об этом первый пример.
Надеюсь, в первом-то примере всё понятно, или тоже нет?

XC>при этом на Скале не писал ни строчки кода вообще, а пример вполне понятен.

Ну извини, Скала — только-только появившийся язык (2004 год). Нафиг бы он был нужен, если б не умел что-то делать лучше, чем существующие языки
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[2]: Структурная и номанативная типизация
От: x-code  
Дата: 18.04.11 07:38
Оценка:
Здравствуйте, Temoto, Вы писали:

XC>>А можно сделать еще лучше? При этом (важно!) не ломая классического синтаксиса обычной номинативной типизации ?


T>def test(f: auto) { println(f.getName) }

Т.е. просто положиться на вывод типов?

И кстати, еще интересный вопрос: какой тип должен использоваться реально для структурной типизации? Специальный "структурный" интерфейс? Как он должен быть устроен на низком уровне?
И как сделать, чтобы в программе отличались "структурные" интерфейсы от "номинативных" (при условии, что в некоторых случаях "номинативные" тоже нужны)?
Re[3]: Структурная и номанативная типизация
От: Temoto  
Дата: 18.04.11 08:23
Оценка:
XC>>>А можно сделать еще лучше? При этом (важно!) не ломая классического синтаксиса обычной номинативной типизации ?

T>>def test(f: auto) { println(f.getName) }

XC>Т.е. просто положиться на вывод типов?

Да. Строго говоря, это скорее будет вывод интерфейса.

XC>И кстати, еще интересный вопрос: какой тип должен использоваться реально для структурной типизации? Специальный "структурный" интерфейс? Как он должен быть устроен на низком уровне?


Да. Специальный анонимный интерфейс для каждого использования объекта.

Не вижу никаких причин, чтобы этот интерфейс был на низком уровне устроен иначе, чем другие интерфейсы. Фактически, код выше можно переписать на этапе проверки типов в

interface test_f_1f8sbdddx {
  getName() : string
}

def test(f: test_f_1f8sbdddx) { println(f.getName) }


XC>И как сделать, чтобы в программе отличались "структурные" интерфейсы от "номинативных" (при условии, что в некоторых случаях "номинативные" тоже нужны)?


Не вижу никаких причин, хотеть чтобы структурные интерфейсы отличались от номинативных. У них всё равно будут отличия: 1) номинативные интерфейсы нужно сначала объявить, 2) следовательно у них есть имя. Но зачем делать ещё какие-то отличия?
Re[4]: Структурная и номанативная типизация
От: x-code  
Дата: 18.04.11 09:01
Оценка:
Здравствуйте, Temoto, Вы писали:

T>Не вижу никаких причин, чтобы этот интерфейс был на низком уровне устроен иначе, чем другие интерфейсы. Фактически, код выше можно переписать на этапе проверки типов в


T>
T>interface test_f_1f8sbdddx {
T>  getName() : string
T>}

T>def test(f: test_f_1f8sbdddx) { println(f.getName) }
T>

И как заставить все используемые там классы наследоваться от этого интерфейса (на низком уровне)? Особенно если многие классы уже в библиотеках в каком-то двоичном виде?

T>Не вижу никаких причин, хотеть чтобы структурные интерфейсы отличались от номинативных. У них всё равно будут отличия: 1) номинативные интерфейсы нужно сначала объявить, 2) следовательно у них есть имя. Но зачем делать ещё какие-то отличия?

Если я например имею именованный интерфейс, но хочу чтобы он был структурным.
Re[5]: Структурная и номанативная типизация
От: Temoto  
Дата: 18.04.11 09:38
Оценка:
T>>Не вижу никаких причин, чтобы этот интерфейс был на низком уровне устроен иначе, чем другие интерфейсы. Фактически, код выше можно переписать на этапе проверки типов в

T>>
T>>interface test_f_1f8sbdddx {
T>>  getName() : string
T>>}

T>>def test(f: test_f_1f8sbdddx) { println(f.getName) }
T>>

XC>И как заставить все используемые там классы наследоваться от этого интерфейса (на низком уровне)? Особенно если многие классы уже в библиотеках в каком-то двоичном виде?

Ну если для корректной работы нужно отнаследовать классы, тогда у нас не структурная типизация.

Наверное, сразу стоило сказать вслух. Я неявно подразумеваю вот что: номинативная типизация это структурная с дополнительными ограничениями (явное указание конкретного интерфейса). Логическим следствием было бы реализовывать в компиляторе только структурную типизацию. И сверху сахаром [никому не нужную] номинативную, которая только вводит дополнительное ограничение к тому что работает.

Вот пример как именно можно выразить номинативный интерфейс:

В коде написано:
interface IFile {
  read() : bytes
  write(bytes)
  close()
}

f : IFile = open(...)
f.close()


Компилятор преобразует в:
f : interface <
  const _InterfaceName = "IFile"
  close()
> = open(...)
f.close()


То есть у интерфейса появляется неизменяемое поле с его именем, которое для проверки типов должно совпадать при каждом использовании. Поскольку поле неизменяемое, эту проверку можно сделать на этапе компиляции.

T>>Не вижу никаких причин, хотеть чтобы структурные интерфейсы отличались от номинативных. У них всё равно будут отличия: 1) номинативные интерфейсы нужно сначала объявить, 2) следовательно у них есть имя. Но зачем делать ещё какие-то отличия?

XC>Если я например имею именованный интерфейс, но хочу чтобы он был структурным.

Сделано. Любой именованый интерфейс является структурным. Аналогия: любая именованая функция является функцией (лямбдой).
Re: Структурная и номанативная типизация
От: z00n  
Дата: 18.04.11 11:37
Оценка: 34 (1)
Здравствуйте, x-code, Вы писали:

XC>Возможно одновременное существование структурной и номинативной типизации в обычном си-подобном языке программирования? Как можно оформить это синтаксически — чтобы было красиво и понятно?


Структурные типы (и вывод типов) есть в Haxe:
http://haxe.org/manual/2_types
http://haxe.org/ref/type_advanced

var p : { x : Int, y : Int }; // declare a typed variable
p = { x : -1, y : 65 }; // OK
p = { x : -1 }; // ERROR : field y is missing
Re: Структурная и номанативная типизация
От: VladD2 Российская Империя www.nemerle.org
Дата: 18.04.11 15:58
Оценка:
Здравствуйте, x-code, Вы писали:

XC>В Go вроде бы тоже есть нечто подобное, но не нашел примера


В Go не поддерживается номинативная система типов. Там только структурная.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Структурная и номанативная типизация
От: VladD2 Российская Империя www.nemerle.org
Дата: 18.04.11 16:11
Оценка:
Здравствуйте, x-code, Вы писали:

XC>Возможно одновременное существование структурной и номинативной типизации в обычном си-подобном языке программирования?


Возможно. Например, в F# записи подчиняются законам структурной типизации принятой в ML, а все остальные типы подчиняются правилам номинативной системы типов.

У меня лично возникают два вопроса по этому поводу:
1. Зачем нужна номинативная типизация в языке где качественно поддерживается структурная?
2. Как эффективно реализовать структурную типизацию в рантаймах на это не рассчитанных (.Net/Mono/Java)? Дело в том, что в этих рантаймах нет нужных средств и в лучшем случае получится эмуляция. А это повлечет или сильные ограничения, или потерю производительности.

Что же касается того как совмещать структурную и номинативную типизации, то тут есть только одно решение, на мой взгляд — разделить типы в языке на те что подчиняются структурной типизации и остальные. Но тут есть нюансы:
1. Ограничить структурную типизацию только этими типами. Так сделано, например, с записями в F#.
2. Дать возможность любой тип приводить к структурному.

Для второго случая я бы ввел некий модификатор для интерфейсов (если оные есть в языке). Например:
structural interface ITest
{
  ...
}
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: Структурная и номанативная типизация
От: VladD2 Российская Империя www.nemerle.org
Дата: 18.04.11 16:26
Оценка:
Здравствуйте, x-code, Вы писали:

XC>И как заставить все используемые там классы наследоваться от этого интерфейса (на низком уровне)? Особенно если многие классы уже в библиотеках в каком-то двоичном виде?


Если язык поддерживает КОП (компонентно-ориентированное программирование), то никак или с серьезным рантайм-верехэдом.
Например, в языке где поддерживаются ссылки на методы объектов можно превратить такой интерфейс с структуру содержащую ссылки на методы. Таким образом код вида (базовый языком взят C#):
interface ITest
{
  int Method1(string s);
  string Prop1 { get; }
}

class A
{
  public Test(structural ITest test)
  {
    var x = test.Method1(test.Prop1);
    ...
  }
}
...
new A().Test(new B());

можно переписать в:
class ITest_Proxy
{
  public Func<string, int> Method1;
  public Func<string>      Prop1;
}

class A
{
  public Test(ITest test)
  {
    var x = test.Method1(test.Prop1);
    ...
  }
}
...
var tempB = new B();
var proxy = new ITest_Proxy() { tempB.Method1; tempB.Prop1; `}
new A().Test(proxy);

Единственная проблема будет в том, что test нельзя будет динамически привести к другому типу, так как работа будет вестись не с родным объектом, а с прокси.

T>>Не вижу никаких причин, хотеть чтобы структурные интерфейсы отличались от номинативных. У них всё равно будут отличия: 1) номинативные интерфейсы нужно сначала объявить, 2) следовательно у них есть имя. Но зачем делать ещё какие-то отличия?

XC>Если я например имею именованный интерфейс, но хочу чтобы он был структурным.

Это не проблема. Как в примере выше можно указывать требование структурной совместимости в параметре или переменной/поле. Ну, а для функций принимающих структурные интерфейсы можно можно просто генерировать два тела. Одно для структурного прокси, а другое для обычной реализации. Правда если таких параметров много, то может начаться комбинаторный взрыв и придется генерировать не столько тел, сколько имеется пересечений структурных интерфейсов.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: Структурная и номанативная типизация
От: jazzer Россия Skype: enerjazzer
Дата: 18.04.11 17:40
Оценка:
Здравствуйте, x-code, Вы писали:

XC>Если я например имею именованный интерфейс, но хочу чтобы он был структурным.


Ну в моем примере на С++ это будет просто набор условий типа того, что уже там есть, объединенный в именованную структуру, которая будет использоваться в коде вместо is_same.

Т.е. будет нечто вроде:
template<class T>
auto MyInterface(T f)
  -> and_<
       is_same< decltype(f.getName()), string >,
       is_same< decltype(f.setName(string)), void >,
       // и т.д., остальные условия
     >::type;

and_<...>::type вернет либо true_, либо false_ (это типы).

Теперь у тебя есть структурный интерфейс с именем MyInterface.
Дальше в пользовательском коде:
template<class T>
void test(T f)
{
  BOOST_MPL_ASSERT((is_same< decltype(MyInterface(f)), true_ >));
  cout << f.getName();
}

Естественно, с помощью элементарного макроса это сводится к
#define CHECK_IFACE(iface) BOOST_MPL_ASSERT((is_same< decltype(iface), true_ >))

template<class T>
void test(T f)
{
  CHECK_IFACE(MyInterface(f));
  cout << f.getName();
}

Аналогично для перегрузок
#define CHECK_IFACE_RET(iface) typename enable_if< is_same< decltype(iface), true_ > >::type

template<class T>
auto test(T f) -> CHECK_IFACE_RET(MyInterface(f))
{
  cout << f.getName();
}


Надеюсь, с макросами тебя это уже не пугает?
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]: Структурная и номанативная типизация
От: x-code  
Дата: 19.04.11 06:06
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Надеюсь, с макросами тебя это уже не пугает?

Пугает то, то что С++ — прямой наследник Си — уходит все дальше и дальше в какие-то дебри, а языки для всяких безопасных тормозных фреймворков становятся все лучше и лучше И где в мире справедливость?
Хотя, надо признать, реализация структурной типизации на шаблонах самая быстрая их всех возможных — для каждого варианта использования будет сгенерирована своя версия функции.
Re[2]: Структурная и номанативная типизация
От: x-code  
Дата: 19.04.11 06:17
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>У меня лично возникают два вопроса по этому поводу:

VD>1. Зачем нужна номинативная типизация в языке где качественно поддерживается структурная?
Не могу строго аргументировать, но кажется, что номинативная "привычнее", естественнее и проще в реализации, и в большинстве случаев ее достаточно.

VD>Что же касается того как совмещать структурную и номинативную типизации, то тут есть только одно решение, на мой взгляд — разделить типы в языке на те что подчиняются структурной типизации и остальные. Но тут есть нюансы:

VD>1. Ограничить структурную типизацию только этими типами. Так сделано, например, с записями в F#.
VD>2. Дать возможность любой тип приводить к структурному.

Да, похоже что так можно, хотя сразу понятно что там огромное количество неочевидных нюансов
Re[7]: Структурная и номанативная типизация
От: jazzer Россия Skype: enerjazzer
Дата: 19.04.11 06:31
Оценка:
Здравствуйте, x-code, Вы писали:

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


J>>Надеюсь, с макросами тебя это уже не пугает?

XC>Пугает то, то что С++ — прямой наследник Си — уходит все дальше и дальше в какие-то дебри, а языки для всяких безопасных тормозных фреймворков становятся все лучше и лучше И где в мире справедливость?
Да ладно тебе, какие же это дебри — автоматический вывод типов, переменное число аргументов у макросов и шаблонов, универсальная инициализация и прочие вкусности? Это все, имхо, делает язык лучше. Т.е. С++0х, имхо, однозначно лучше С++98.
А если не рассматривать С++0х, то в дебри уходят программисты, а не язык Буст, Александреску, шаблонное и препроцессорное метарограммирование — это все реализовано на базе старого доброго С++98

XC>Хотя, надо признать, реализация структурной типизации на шаблонах самая быстрая их всех возможных — для каждого варианта использования будет сгенерирована своя версия функции.

Да, все эти игры с типизацией в С++ остаются на стадии компиляции, а после того, как сгенерены и проверены все типы, идет обычная кодогенерация сишного уровня, со всеми подобающими оптимизациями, специфическими для результирующего типа. Т.е. сколько бы я проверок не навернул во время компиляции, если компилятор не кривой, они никакого влияния на скорость исполнения скомпилированного кода не окажут.
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[3]: Структурная и номанативная типизация
От: VladD2 Российская Империя www.nemerle.org
Дата: 19.04.11 17:31
Оценка:
Здравствуйте, x-code, Вы писали:

XC>Не могу строго аргументировать, но кажется, что номинативная "привычнее", естественнее и проще в реализации, и в большинстве случаев ее достаточно.


Привычнее то что использовал. Ваш, КО.

А вот структурная система типов гибче. Нет многих проблем присущих номинативной системе.

В качестве примера могу привести дженерики дотнета и шаблоны С++. Первые имеют известную проблему. Ограничения для параметров типов в дженериках указываются в полном соответствии с канонами номинативной системы типов — через именованные интерфейсы. Реализация интерфейса должна быть явно описана при декларации типа. Таким образом, если кто-то наложил ограничения на параметр типа, то вместо него нельзя передать не реализующий интерфейс даже если этот тип полностью подходит по функциональности.

В структурной системе типов это не было бы проблемой.

VD>>Что же касается того как совмещать структурную и номинативную типизации, то тут есть только одно решение, на мой взгляд — разделить типы в языке на те что подчиняются структурной типизации и остальные. Но тут есть нюансы:

VD>>1. Ограничить структурную типизацию только этими типами. Так сделано, например, с записями в F#.
VD>>2. Дать возможность любой тип приводить к структурному.

XC>Да, похоже что так можно, хотя сразу понятно что там огромное количество неочевидных нюансов


Например?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Структурная и номанативная типизация
От: FR  
Дата: 21.04.11 06:38
Оценка:
Здравствуйте, x-code, Вы писали:

VD>>1. Зачем нужна номинативная типизация в языке где качественно поддерживается структурная?

XC>Не могу строго аргументировать, но кажется, что номинативная "привычнее", естественнее и проще в реализации, и в большинстве случаев ее достаточно.

Структурная для понимания как раз проще, да и для языков с выводом типов естественнее.
Re[4]: Структурная и номанативная типизация
От: VoidEx  
Дата: 21.04.11 07:43
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, x-code, Вы писали:


XC>>Не могу строго аргументировать, но кажется, что номинативная "привычнее", естественнее и проще в реализации, и в большинстве случаев ее достаточно.


VD>Привычнее то что использовал. Ваш, КО.


VD>А вот структурная система типов гибче. Нет многих проблем присущих номинативной системе.


VD>В качестве примера могу привести дженерики дотнета и шаблоны С++. Первые имеют известную проблему. Ограничения для параметров типов в дженериках указываются в полном соответствии с канонами номинативной системы типов — через именованные интерфейсы. Реализация интерфейса должна быть явно описана при декларации типа. Таким образом, если кто-то наложил ограничения на параметр типа, то вместо него нельзя передать не реализующий интерфейс даже если этот тип полностью подходит по функциональности.


VD>В структурной системе типов это не было бы проблемой.


Было бы. У функций в интерфейсе тоже есть имена. Как предлагается проверять структурное соответствие для них?
interface IShow
{
    string toString();
}

и
class Some
{
    string fileName() { return "1.txt"; }
}


Проблема тут не в имени, а в невозможности по месту "отнаследовать".
Re[5]: Структурная и номанативная типизация
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.04.11 15:12
Оценка: +1
Здравствуйте, VoidEx, Вы писали:

VE>Было бы. У функций в интерфейсе тоже есть имена. Как предлагается проверять структурное соответствие для них?


В структурных системах типов обычно и производится проверка по именам членов.

VE>Проблема тут не в имени, а в невозможности по месту "отнаследовать".


В структурных системах типов наследование не обязательно. Там достаточно понятия подтипа. А наследование если и есть, то является средством повторного использования кода, а не средством полиморфизма.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: Структурная и номанативная типизация
От: VoidEx  
Дата: 22.04.11 08:40
Оценка:
Здравствуйте, VladD2, Вы писали:

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


VE>>Было бы. У функций в интерфейсе тоже есть имена. Как предлагается проверять структурное соответствие для них?


VD>В структурных системах типов обычно и производится проверка по именам членов.


Вот именно.
interface IToString { string toString(); }

class MyData { string asString(); }
class MyData2 { list<char> toString(); }

Соответствует MyData или нет? А MyData2?
Re[7]: Структурная и номанативная типизация
От: FR  
Дата: 22.04.11 12:04
Оценка:
Здравствуйте, VoidEx, Вы писали:

VE>Вот именно.

VE>
VE>interface IToString { string toString(); }

VE>class MyData { string asString(); }
VE>class MyData2 { list<char> toString(); }
VE>

VE>Соответствует MyData или нет? А MyData2?

В OCaml сопоставление происходит по сигнатуре функции то есть по кортежу (<возвращаемое значение>, <имя функции>, <параметры>)
при этом возвращаемое значение и параметры максимально возможно обобщаются и условно для функции

int CountChars(o)
{
return fold(enum(o.toString()), (sum, c) => sum + 1)
}


подойдут и IToString и MyData2
Re[8]: Структурная и номанативная типизация
От: VoidEx  
Дата: 22.04.11 12:30
Оценка:
Здравствуйте, FR, Вы писали:

FR>В OCaml сопоставление происходит по сигнатуре функции то есть по кортежу (<возвращаемое значение>, <имя функции>, <параметры>)

FR>при этом возвращаемое значение и параметры максимально возможно обобщаются и условно для функции

FR>
FR>int CountChars(o)
FR>{
FR>return fold(enum(o.toString()), (sum, c) => sum + 1)
FR>}
FR>


FR>подойдут и IToString и MyData2


Можно ли вызвать так, чтобы MyData тоже подошло? Какой нужен дополнительный код?
Re[9]: Структурная и номанативная типизация
От: FR  
Дата: 22.04.11 12:52
Оценка:
Здравствуйте, VoidEx, Вы писали:


FR>>подойдут и IToString и MyData2


VE>Можно ли вызвать так, чтобы MyData тоже подошло? Какой нужен дополнительный код?


Нет, совпадение имени необходимо.
Re[10]: Структурная и номанативная типизация
От: VoidEx  
Дата: 22.04.11 13:00
Оценка:
Здравствуйте, FR, Вы писали:

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



FR>>>подойдут и IToString и MyData2


VE>>Можно ли вызвать так, чтобы MyData тоже подошло? Какой нужен дополнительный код?


FR>Нет, совпадение имени необходимо.


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

Было бы куда лучше, например, так:
foo(myData { toString = asString })


Или вообще уровня scope:
let instance IsString MyData where
  toString = asString
in
  ...
Re[11]: Структурная и номанативная типизация
От: FR  
Дата: 22.04.11 14:13
Оценка:
Здравствуйте, VoidEx, Вы писали:

FR>>Нет, совпадение имени необходимо.


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


Вообще не вижу смысла зачем надо что-то городить
Re[7]: Структурная и номанативная типизация
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.04.11 15:10
Оценка:
Здравствуйте, VoidEx, Вы писали:

VE>Вот именно.


Что, именно?

VE>
VE>interface IToString { string toString(); }

VE>class MyData { string asString(); }
VE>class MyData2 { list<char> toString(); }
VE>

VE>Соответствует MyData или нет?

Нет. Но, вроде как есть языки позволяющие задавать отображения.

VE>А MyData2?


Нет.

Вообще, структурная типизация подразумевает, что имя метода члена в совокупности с его сигнатурой определяет его предназначение. И обычно так и есть.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: Структурная и номанативная типизация
От: VoidEx  
Дата: 22.04.11 19:11
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Вообще, структурная типизация подразумевает, что имя метода члена в совокупности с его сигнатурой определяет его предназначение. И обычно так и есть.


сразу в голову приходят length/size/count, а в некоторых контекстах на их место может претендовать и vertices/numPoints/etc.
Неплохо было бы (очень неплохо) уметь указывать по месту, мол в данном случае за length можно считать vertices.
Re[9]: Структурная и номанативная типизация
От: Temoto  
Дата: 25.04.11 08:24
Оценка:
VD>>Вообще, структурная типизация подразумевает, что имя метода члена в совокупности с его сигнатурой определяет его предназначение. И обычно так и есть.

VE>сразу в голову приходят length/size/count, а в некоторых контекстах на их место может претендовать и vertices/numPoints/etc.

VE>Неплохо было бы (очень неплохо) уметь указывать по месту, мол в данном случае за length можно считать vertices.

Для совместимости волей неволей большинство разработчиков придут к единому соглашению.
Re[2]: Структурная и номанативная типизация
От: nikov США http://www.linkedin.com/in/nikov
Дата: 27.04.11 22:04
Оценка: 1 (1)
Здравствуйте, VladD2, Вы писали:

VD>Возможно. Например, в F# записи подчиняются законам структурной типизации принятой в ML, а все остальные типы подчиняются правилам номинативной системы типов.


Да ладно тебе. Покажи-ка пример структурной типизации для записей.
Re[2]: Структурная и номанативная типизация
От: vdimas Россия  
Дата: 27.04.11 22:42
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>1. Зачем нужна номинативная типизация в языке где качественно поддерживается структурная?


Хотя бы для полноценного ООП, чтобы тип А { int i; } отличать от такого же типа B { int i; }
Re[4]: Структурная и номанативная типизация
От: vdimas Россия  
Дата: 27.04.11 22:45
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>В качестве примера могу привести дженерики дотнета и шаблоны С++. Первые имеют известную проблему. Ограничения для параметров типов в дженериках указываются в полном соответствии с канонами номинативной системы типов — через именованные интерфейсы. Реализация интерфейса должна быть явно описана при декларации типа. Таким образом, если кто-то наложил ограничения на параметр типа, то вместо него нельзя передать не реализующий интерфейс даже если этот тип полностью подходит по функциональности.


VD>В структурной системе типов это не было бы проблемой.


А как же бинарный контракт? Либо весь исходник с собой таскать надо, для целей кодогенерации под конкретный "клиентский" тип, либо разделить объявление типов и их реализацию, но зафиксировать в каком-либо виде бинарный контракт м/у объявлением и реализацией.
Re[3]: Структурная и номанативная типизация
От: FR  
Дата: 28.04.11 02:11
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Хотя бы для полноценного ООП, чтобы тип А { int i; } отличать от такого же типа B { int i; }

V>

Не полноценного а привычного.
Re[4]: Структурная и номанативная типизация
От: vdimas Россия  
Дата: 28.04.11 07:54
Оценка:
Здравствуйте, FR, Вы писали:

FR>Не полноценного а привычного.


Пока что считается, что в этом и состоит сильная статическая типизация, чтобы компилятор помогал ловить ошибки семантики, коль мы наделяем A и B разной семантикой. ИМХО, в С++ очень удачное название название у шаблонов, намекающее на то, что это не сам код. Т.е. мы вроде как не статическую типизацию в теле шаблона нарушаем, а скромно генерим другой код по образцу и подобию.
Re[5]: Структурная и номанативная типизация
От: FR  
Дата: 29.04.11 15:01
Оценка:
Здравствуйте, vdimas, Вы писали:

FR>>Не полноценного а привычного.


V>Пока что считается, что в этом и состоит сильная статическая типизация, чтобы компилятор помогал ловить ошибки семантики, коль мы наделяем A и B разной семантикой.


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

V>ИМХО, в С++ очень удачное название название у шаблонов, намекающее на то, что это не сам код. Т.е. мы вроде как не статическую типизацию в теле шаблона нарушаем, а скромно генерим другой код по образцу и подобию.


Шаблоны C++ (да и D) это все-таки не совсем структурная типизация, а нечто на нее очень похожее. В том же OCaml статическая типизация нигде ни нарушается, и структурно типизированные функции шаблонами не являются.
Re[6]: Структурная и номанативная типизация
От: jazzer Россия Skype: enerjazzer
Дата: 05.05.11 02:27
Оценка:
Здравствуйте, FR, Вы писали:

FR>>>Не полноценного а привычного.


V>>Пока что считается, что в этом и состоит сильная статическая типизация, чтобы компилятор помогал ловить ошибки семантики, коль мы наделяем A и B разной семантикой.


FR>Это в тебе голос привычного ОО говорит, при структурной типизации никаких классов по сути нет, есть объекты и есть методы объектов и семантика должна быть завязана именно на это, а не на мифические классы


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

(Хотя в С++, в котором можно в "структурную" типизцию на шаблонах впихнуть типы и вообще все, что угодно (traits, например), можно эмулировать и нормальную типизацию через те же traits. Но в С++ шаблоны намного мощнее простой стуктурной типизации. Структурная типизация — это просто кастрированная версия предикатной типизации (когда можно задать любой вопрос относительно типа), в которой предикаты ограничены примитивными "есть член с таким именем и сигнатурой")

V>>ИМХО, в С++ очень удачное название название у шаблонов, намекающее на то, что это не сам код. Т.е. мы вроде как не статическую типизацию в теле шаблона нарушаем, а скромно генерим другой код по образцу и подобию.


FR>Шаблоны C++ (да и D) это все-таки не совсем структурная типизация, а нечто на нее очень похожее.


"нечто на нее очень похожее" — в терминах duck typing это высказывание эквивалентно "это оно и есть"
Если спор не чисто терминологический, конечно.

FR>В том же OCaml статическая типизация нигде ни нарушается, и структурно типизированные функции шаблонами не являются.

И как они работают на бинарном уровне тогда? Вот у тебя есть функция, и ты ее зовешь с тремя абсолютно по-разному устроенными, но структурно-совместимыми объектами. В С++ для каждого вызова сгенерится код, наиболее подходящий для каждого типа (т.е. если искомая функция в одном объекте виртуальная, а в другом — нет, то будут сгенерены виртуальный и невиртуальный вызовы соответственно). Что генерит компилятор окамла?
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[7]: Структурная и номанативная типизация
От: FR  
Дата: 10.05.11 11:04
Оценка:
Здравствуйте, jazzer, Вы писали:

FR>>Это в тебе голос привычного ОО говорит, при структурной типизации никаких классов по сути нет, есть объекты и есть методы объектов и семантика должна быть завязана именно на это, а не на мифические классы


J>И как структурная типизация позволит защититься от сравнения яблок с апельсинами?


Вот вопрос как раз и показывает отличия в мышлении, меня самого правда тоже клинит
Что такое яблоки и апельсины? Классы? А нет их в нашем ОО есть только объекты и если они позволяют друг друга
сравнивать то и будут успешно сравнены, не позволяют не будут.

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


Не совсем они ортогональны очень прилично пересекаются. а сосуществовать конечно вполне могут.

J>(Хотя в С++, в котором можно в "структурную" типизцию на шаблонах впихнуть типы и вообще все, что угодно (traits, например), можно эмулировать и нормальную типизацию через те же traits. Но в С++ шаблоны намного мощнее простой стуктурной типизации. Структурная типизация — это просто кастрированная версия предикатной типизации (когда можно задать любой вопрос относительно типа), в которой предикаты ограничены примитивными "есть член с таким именем и сигнатурой")


Про предикатную не слышал и достаточно трудно для меня представимо.

FR>>Шаблоны C++ (да и D) это все-таки не совсем структурная типизация, а нечто на нее очень похожее.


J>"нечто на нее очень похожее" — в терминах duck typing это высказывание эквивалентно "это оно и есть"

J>Если спор не чисто терминологический, конечно.

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

FR>>В том же OCaml статическая типизация нигде ни нарушается, и структурно типизированные функции шаблонами не являются.

J>И как они работают на бинарном уровне тогда? Вот у тебя есть функция, и ты ее зовешь с тремя абсолютно по-разному устроенными, но структурно-совместимыми объектами. В С++ для каждого вызова сгенерится код, наиболее подходящий для каждого типа (т.е. если искомая функция в одном объекте виртуальная, а в другом — нет, то будут сгенерены виртуальный и невиртуальный вызовы соответственно). Что генерит компилятор окамла?

На бинарном как обычные, (вернее не совсем обычные http://lj.rossia.org/community/programming/920.html) вызовы.
Re[8]: Структурная и номанативная типизация
От: jazzer Россия Skype: enerjazzer
Дата: 10.05.11 12:09
Оценка:
Здравствуйте, FR, Вы писали:

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


FR>>>Это в тебе голос привычного ОО говорит, при структурной типизации никаких классов по сути нет, есть объекты и есть методы объектов и семантика должна быть завязана именно на это, а не на мифические классы


J>>И как структурная типизация позволит защититься от сравнения яблок с апельсинами?


FR>Вот вопрос как раз и показывает отличия в мышлении, меня самого правда тоже клинит

FR>Что такое яблоки и апельсины? Классы? А нет их в нашем ОО есть только объекты и если они позволяют друг друга
FR>сравнивать то и будут успешно сравнены, не позволяют не будут.

Это сущности предметной области, устроенные одинаково, но с разным смыслом. И ты хочешь, чтоб компилятор не дал тебе написать код, которые позволит сравнить несравнимое.
В стандартно-типизированном языке это понятно как делается — разные типы. Они могут быть устроены внутри как угодно, в том числе и одинаково, главное, что они сами по себе разные, и на этом можно построить проверки.
Что мне делать в структурно-типизированном языке, чтоб получить такой же силы проверки? Делать разную структуру? Ну это же изврат. Та же пара чисел — это может быть просто пара, а может быть размер, а может быть точка на плоскости, а может быть комплексное число...

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


FR>Не совсем они ортогональны очень прилично пересекаются. а сосуществовать конечно вполне могут.

В чем же они пересекаются, если обычно-типизированные построены на понятии type identity (см выше)?

J>>(Хотя в С++, в котором можно в "структурную" типизцию на шаблонах впихнуть типы и вообще все, что угодно (traits, например), можно эмулировать и нормальную типизацию через те же traits. Но в С++ шаблоны намного мощнее простой стуктурной типизации. Структурная типизация — это просто кастрированная версия предикатной типизации (когда можно задать любой вопрос относительно типа), в которой предикаты ограничены примитивными "есть член с таким именем и сигнатурой")


FR>Про предикатную не слышал и достаточно трудно для меня представимо.


Предикатная — это когда ты просто говоришь: "функция принимает нечто, удовлетворяющее следующему набору условий", где условия могут быть какими угодно. Если ты ограничиваешь условия так: "тип должен быть только А или его наследником" — ты получаешь обычную ООП-типизацию. Если "тип должен содержать такие-то методы с такими-то сигнатурами" — получаешь структурную. С шаблоанми С++ ты можешь делать что угодно — хоть структурную, хоть ООП, хоть "помесь бобика со свиньёй" (с) типа "тип должен быть А или Б, или их наследники, но не прямые, а через одного, и содержать при этом такие-то методы, и еще чтоб у них был вложенный тип iterator с такими-то методами, и чтоб у вот этого метода возвращаемый тип удовлетворял предикату, который юзер передал первым параметром".

FR>>>Шаблоны C++ (да и D) это все-таки не совсем структурная типизация, а нечто на нее очень похожее.


J>>"нечто на нее очень похожее" — в терминах duck typing это высказывание эквивалентно "это оно и есть"

J>>Если спор не чисто терминологический, конечно.

FR>Нет есть вполне реальные отличия, главное шаблоны это именно шаблоны в которые что-то можно подставить и только после этого

FR>понять подходит это или нет. В структурной наоборот из использования в функции мы выводим тип который наша функция может
FR>принять.
Разницы не уловил

FR>>>В том же OCaml статическая типизация нигде ни нарушается, и структурно типизированные функции шаблонами не являются.

J>>И как они работают на бинарном уровне тогда? Вот у тебя есть функция, и ты ее зовешь с тремя абсолютно по-разному устроенными, но структурно-совместимыми объектами. В С++ для каждого вызова сгенерится код, наиболее подходящий для каждого типа (т.е. если искомая функция в одном объекте виртуальная, а в другом — нет, то будут сгенерены виртуальный и невиртуальный вызовы соответственно). Что генерит компилятор окамла?

FR>На бинарном как обычные, (вернее не совсем обычные http://lj.rossia.org/community/programming/920.html) вызовы.

клёво! (интересно, клёво — это калька с clever?)
Правда, все равно получаются ран-тайм проверки на нули в соответствующих местах таблицы, если я правильно понял, плюс дополнительный уровень косвенности. Никакие невиртуальные вызовы и заточка под конкретный тип невозможна. Не говоря уже о том, что нечто может быть не функцией, а объектом-функтором (хотя, может, в окамле этого нет в принципе).
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[8]: Структурная и номанативная типизация
От: Jack128  
Дата: 10.05.11 12:09
Оценка:
Здравствуйте, FR, Вы писали:

FR>На бинарном как обычные, (вернее не совсем обычные http://lj.rossia.org/community/programming/920.html) вызовы.


Я правильно понял, что в OCaml каждый _объект_ (не класс) содержит свою VMT ?? Что то мне кажется не шибко эффективно по памяти.
Re[9]: Структурная и номанативная типизация
От: FR  
Дата: 10.05.11 12:51
Оценка:
Здравствуйте, jazzer, Вы писали:

FR>>Что такое яблоки и апельсины? Классы? А нет их в нашем ОО есть только объекты и если они позволяют друг друга

FR>>сравнивать то и будут успешно сравнены, не позволяют не будут.

J>Это сущности предметной области, устроенные одинаково, но с разным смыслом. И ты хочешь, чтоб компилятор не дал тебе написать код, которые позволит сравнить несравнимое.


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

J>В стандартно-типизированном языке это понятно как делается — разные типы. Они могут быть устроены внутри как угодно, в том числе и одинаково, главное, что они сами по себе разные, и на этом можно построить проверки.


Так и в структурном также, просто нужно помнить что разными должны быть имена методов, а не имена классов.

J>Что мне делать в структурно-типизированном языке, чтоб получить такой же силы проверки? Делать разную структуру? Ну это же изврат. Та же пара чисел — это может быть просто пара, а может быть размер, а может быть точка на плоскости, а может быть комплексное число...


Просто давать разные имена методам, имя часть сигнатуры.

FR>>Не совсем они ортогональны очень прилично пересекаются. а сосуществовать конечно вполне могут.

J>В чем же они пересекаются, если обычно-типизированные построены на понятии type identity (см выше)?

В решаемых задачах.

FR>>Про предикатную не слышал и достаточно трудно для меня представимо.


J>Предикатная — это когда ты просто говоришь: "функция принимает нечто, удовлетворяющее следующему набору условий", где условия могут быть какими угодно. Если ты ограничиваешь условия так: "тип должен быть только А или его наследником" — ты получаешь обычную ООП-типизацию. Если "тип должен содержать такие-то методы с такими-то сигнатурами" — получаешь структурную. С шаблоанми С++ ты можешь делать что угодно — хоть структурную, хоть ООП, хоть "помесь бобика со свиньёй" (с) типа "тип должен быть А или Б, или их наследники, но не прямые, а через одного, и содержать при этом такие-то методы, и еще чтоб у них был вложенный тип iterator с такими-то методами, и чтоб у вот этого метода возвращаемый тип удовлетворял предикату, который юзер передал первым параметром".


Понятно, но это что-то слишком обще размытое.

FR>>Нет есть вполне реальные отличия, главное шаблоны это именно шаблоны в которые что-то можно подставить и только после этого

FR>>понять подходит это или нет. В структурной наоборот из использования в функции мы выводим тип который наша функция может
FR>>принять.
J>Разницы не уловил

Разница как-раз в возможностях статического контроля. Для структурной он не теряется.


FR>>На бинарном как обычные, (вернее не совсем обычные http://lj.rossia.org/community/programming/920.html) вызовы.

J>клёво! (интересно, клёво — это калька с clever?)

( Рыбаки говорят от слова клевать )

J>Правда, все равно получаются ран-тайм проверки на нули в соответствующих местах таблицы, если я правильно понял, плюс дополнительный уровень косвенности. Никакие невиртуальные вызовы и заточка под конкретный тип невозможна. Не говоря уже о том, что нечто может быть не функцией, а объектом-функтором (хотя, может, в окамле этого нет в принципе).


Да вызов по сути виртуальный, заточка под конкретный тип как в шаблонах в виде частичной специализации и т. п. невозможна, но компилятор если тип задан жестко может соптимизировать и подставить прямой вызов.
Объект-функтор для полноценного ФП языка конечно бессмыслен, хотя в принципе наверно можно сделать.
Re[9]: Структурная и номанативная типизация
От: FR  
Дата: 10.05.11 13:15
Оценка:
Здравствуйте, Jack128, Вы писали:

J>Я правильно понял, что в OCaml каждый _объект_ (не класс) содержит свою VMT ?? Что то мне кажется не шибко эффективно по памяти.


Каждый экземпляр объекта (созданный new) конечно не содержит свою VMT. У всех структурно совпадающих объектов будет общая VMT.
Например для:
class elephant = 
  object
    method say = printf "elephant\n"
  end

(* с точки зрения компилятора этот класс совпадает с elephant *)
class mamont = 
  object
    method say = printf "mamont\n"
  end


class dog = 
  object    
    method say = printf "dog\n"
    method dog_id = ()
  end

class wolf = 
  object
    method say = printf "wolf\n"
    method wolf_id = ()
  end


let elephant1_ = new elephant
let elephant2_ = new elephant
let mamont_ = new mamont
let dog_ = new dog
let wolf_ = new wolf


У elephant1_, elephant2_ и mamont_ будет одна и та же VMT.
Re[10]: Структурная и номанативная типизация
От: jazzer Россия Skype: enerjazzer
Дата: 11.05.11 09:28
Оценка:
Здравствуйте, FR, Вы писали:

FR>>>Что такое яблоки и апельсины? Классы? А нет их в нашем ОО есть только объекты и если они позволяют друг друга

FR>>>сравнивать то и будут успешно сравнены, не позволяют не будут.

J>>Это сущности предметной области, устроенные одинаково, но с разным смыслом. И ты хочешь, чтоб компилятор не дал тебе написать код, которые позволит сравнить несравнимое.


FR>Без проблем, ничто ни мешает если они разные хоть и устроенные одинаково называть методы этих объектов по разному.

Т.е. программер должен прошерстить все совместимыые классы и убедиться, что новый класс, который он пишет, имеет уникальные имена? Звучит несколько непрактично, не?

FR>В мейнстримном ООП только копи-паст будет чуть проще в этом случае.

При чем тут копи-паст? Я про типобезопасность.

J>>В стандартно-типизированном языке это понятно как делается — разные типы. Они могут быть устроены внутри как угодно, в том числе и одинаково, главное, что они сами по себе разные, и на этом можно построить проверки.


FR>Так и в структурном также, просто нужно помнить что разными должны быть имена методов, а не имена классов.

см. выше.
Или ты предлагаешь в каждом классе завести метод типа this_is_apple, this_is_orange и матчить по нему?

J>>Что мне делать в структурно-типизированном языке, чтоб получить такой же силы проверки? Делать разную структуру? Ну это же изврат. Та же пара чисел — это может быть просто пара, а может быть размер, а может быть точка на плоскости, а может быть комплексное число...

FR>Просто давать разные имена методам, имя часть сигнатуры.
см. выше.

FR>>>Не совсем они ортогональны очень прилично пересекаются. а сосуществовать конечно вполне могут.

J>>В чем же они пересекаются, если обычно-типизированные построены на понятии type identity (см выше)?
FR>В решаемых задачах.

Я говорю, что фичи ортогональны (а не взаимоисключающи). Естественно, ортогональные фичи пересекаются в реальных задачах.

FR>>>Про предикатную не слышал и достаточно трудно для меня представимо.

J>>Предикатная — это когда ты просто говоришь: "функция принимает нечто, удовлетворяющее следующему набору условий", где условия могут быть какими угодно.
FR>Понятно, но это что-то слишком обще размытое.
Тем не менее в шаблонах С++ это прекрасно работает.
Что я делаю не так?

FR>>>Нет есть вполне реальные отличия, главное шаблоны это именно шаблоны в которые что-то можно подставить и только после этого

FR>>>понять подходит это или нет. В структурной наоборот из использования в функции мы выводим тип который наша функция может
FR>>>принять.
J>>Разницы не уловил

FR>Разница как-раз в возможностях статического контроля. Для структурной он не теряется.

А в шаблонах он теряется, что ли?

FR>Да вызов по сути виртуальный, заточка под конкретный тип как в шаблонах в виде частичной специализации и т. п. невозможна, но компилятор если тип задан жестко может соптимизировать и подставить прямой вызов.

Ну тогда неинтересно.

FR>Объект-функтор для полноценного ФП языка конечно бессмыслен, хотя в принципе наверно можно сделать.

Ну вот Питон — это полноценный ФП-язык? А в нем функторы есть.

ЗЫ В сигнатуре метода, кроме имени, проверяются также и типы аргументов — т.е. обычные типы все-таки нужны даже структурной типизации
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]: Структурная и номанативная типизация
От: FR  
Дата: 12.05.11 03:51
Оценка:
Здравствуйте, jazzer, Вы писали:

FR>>Без проблем, ничто ни мешает если они разные хоть и устроенные одинаково называть методы этих объектов по разному.

J>Т.е. программер должен прошерстить все совместимыые классы и убедиться, что новый класс, который он пишет, имеет уникальные имена? Звучит несколько непрактично, не?

С точки зрения "классового" программиста конечно.
Но если у нас с самого начала дизайн был завязан на объекты и методы то нет.

FR>>В мейнстримном ООП только копи-паст будет чуть проще в этом случае.

J>При чем тут копи-паст? Я про типобезопасность.

Ну в обоих случаях для сущности предметной области, устроенные одинаково, но с разным смыслом придется дублировать
код.
А типобезопасность в структурном ОО никак ни меньше чем в номинативном, просто не стоит забывать что
типы там образуются по разному.

FR>>Так и в структурном также, просто нужно помнить что разными должны быть имена методов, а не имена классов.

J>см. выше.
J>Или ты предлагаешь в каждом классе завести метод типа this_is_apple, this_is_orange и матчить по нему?

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

FR>>Понятно, но это что-то слишком обще размытое.

J>Тем не менее в шаблонах С++ это прекрасно работает.

Что не отменяет размытость
В питоне с декораторами этот же подход тоже вполне себе прекрасно работает, при еще большей размытости.

FR>>Разница как-раз в возможностях статического контроля. Для структурной он не теряется.

J>А в шаблонах он теряется, что ли?

Частично да, просто в подстановочной модели это по моему неизбежно. Тот же SFINAE как пример.

FR>>Да вызов по сути виртуальный, заточка под конкретный тип как в шаблонах в виде частичной специализации и т. п. невозможна, но компилятор если тип задан жестко может соптимизировать и подставить прямой вызов.

J>Ну тогда неинтересно.

Неинтерсно если как в С++ нужны побочные эффекты шаблонов.

FR>>Объект-функтор для полноценного ФП языка конечно бессмыслен, хотя в принципе наверно можно сделать.

J>Ну вот Питон — это полноценный ФП-язык? А в нем функторы есть.

При всей мой любви к питону на полноценный ФП язык он не тянет. Нет неизменяемых данных, нет раскрутки хвостовой рекурсии.
А функторы там необходимы из-за неполноценности замыканий, при захвате переменные превращаются в немутабельные.

J>ЗЫ В сигнатуре метода, кроме имени, проверяются также и типы аргументов — т.е. обычные типы все-таки нужны даже структурной типизации


Конечно
Вообще по моему структурный ОО хорош именно как дополнение к другим мощным свойствам языка, например как в OCaml.
Re[12]: Структурная и номанативная типизация
От: jazzer Россия Skype: enerjazzer
Дата: 12.05.11 05:36
Оценка:
Здравствуйте, FR, Вы писали:

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


FR>>>Без проблем, ничто ни мешает если они разные хоть и устроенные одинаково называть методы этих объектов по разному.

J>>Т.е. программер должен прошерстить все совместимыые классы и убедиться, что новый класс, который он пишет, имеет уникальные имена? Звучит несколько непрактично, не?

FR>С точки зрения "классового" программиста конечно.

FR>Но если у нас с самого начала дизайн был завязан на объекты и методы то нет.
Можешь привести пример? А то общие слова только.
Вот реальный пример неудобства, который, имхо, структурной типизацией не решается, ибо интерфейс у всех числовых типов в принципе одинаковый, независимо от смысла: http://www.rsdn.ru/forum/cpp/4266827.1.aspx
Автор: B0FEE664
Дата: 11.05.11


FR>>>В мейнстримном ООП только копи-паст будет чуть проще в этом случае.

J>>При чем тут копи-паст? Я про типобезопасность.

FR>Ну в обоих случаях для сущности предметной области, устроенные одинаково, но с разным смыслом придется дублировать

FR>код.
Про дублирование кода я не говорил, с ним все очевидно. Я про типобезопасность.

FR>А типобезопасность в структурном ОО никак ни меньше чем в номинативном, просто не стоит забывать что

FR>типы там образуются по разному.
Ну да, и в результате куча типов неожиданно оказываются подходящими. Где безопасность?

FR>>>Так и в структурном также, просто нужно помнить что разными должны быть имена методов, а не имена классов.

J>>см. выше.
J>>Или ты предлагаешь в каждом классе завести метод типа this_is_apple, this_is_orange и матчить по нему?

FR>Нет я предлагаю плясать не от мифических в случае структурной типизации классов а от объектов и методов.

У абсолютно разных и несовместимых по смыслу объектов могут быть одинаковые по сигнатурам и разные по смыслу методы, с этим-то ты согласен?
Причем даже если их нет сейчас, они могут появиться завтра, потому что сосед-программер добавил новый метод.
Как мне теперь сделать так, чтоб компилятор несовместимые объекты не пропустил и дал ошибку компиляции?

FR>>>Понятно, но это что-то слишком обще размытое.

J>>Тем не менее в шаблонах С++ это прекрасно работает.
FR>Что не отменяет размытость
FR>В питоне с декораторами этот же подход тоже вполне себе прекрасно работает, при еще большей размытости.
Отсюда следует вывод, что размытость не имеет физического смысла, раз все прекрасно работает

FR>>>Разница как-раз в возможностях статического контроля. Для структурной он не теряется.

J>>А в шаблонах он теряется, что ли?
FR>Частично да, просто в подстановочной модели это по моему неизбежно. Тот же SFINAE как пример.
И где тут что теряется? Можно пример?

FR>>>Да вызов по сути виртуальный, заточка под конкретный тип как в шаблонах в виде частичной специализации и т. п. невозможна, но компилятор если тип задан жестко может соптимизировать и подставить прямой вызов.

J>>Ну тогда неинтересно.
FR>Неинтерсно если как в С++ нужны побочные эффекты шаблонов.
Что ты называешь побочными эффектами шаблонов? Частичную специализацию? Возможность заточки под тип? SFINAE? это все прямые эффекты, это то, зачем шаблоны вообще делались. У шаблонов С++ единственный побочный эфект — шаблонное метапрограммирование, но здесь оно не при делах.


FR>>>Объект-функтор для полноценного ФП языка конечно бессмыслен, хотя в принципе наверно можно сделать.

J>>Ну вот Питон — это полноценный ФП-язык? А в нем функторы есть.
FR>При всей мой любви к питону на полноценный ФП язык он не тянет. Нет неизменяемых данных, нет раскрутки хвостовой рекурсии.
FR>А функторы там необходимы из-за неполноценности замыканий, при захвате переменные превращаются в немутабельные.
То у тебя плохо, что нет неизменяемых данных, то что переменные становятся неизменяемые Ты уж определись

J>>ЗЫ В сигнатуре метода, кроме имени, проверяются также и типы аргументов — т.е. обычные типы все-таки нужны даже структурной типизации


FR>Конечно

FR>Вообще по моему структурный ОО хорош именно как дополнение к другим мощным свойствам языка, например как в OCaml.
Тут полностью согласен. На одной структурной типизации нормальной безопасной системы программирования, имхо, не напишешь. Но в качестве приправы — очень даже вкусненько.

Обычная типизация призвана отражать предметную область приложения, а структурная построена на артефактах объектов.
Т.е. программы в любом случае пишутся в терминах типов ("перевести деньги с этого счета на тот"), а не в терминах того, что можно сделать с произвольных объектом ("взять две любые фигни, у которых есть методы add и subtract, и которые принимают третью фигню, отнять третью у первого, добавить третью второму").
Стандартная типизация консервативна и закрыта, т.е. то, что явно не объявлено совместимым, совместимым не является, даже если одно — полный копипейст другого. Уже поэтому она гораздо более безопасна и надежна, но ценой гибкости, естественно. А структурная — наоборот: все может быть совместимым, гибкости хоть отбавляй, зато безопасность так себе. Предикатная охватывает оба варианта, так что в зависимости от стиля ее использования можно получить требуемый баланс между безопасностью и гибкостью.
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]: Структурная и номанативная типизация
От: FR  
Дата: 12.05.11 07:35
Оценка:
Здравствуйте, jazzer, Вы писали:

FR>>Но если у нас с самого начала дизайн был завязан на объекты и методы то нет.

J>Можешь привести пример? А то общие слова только.

В структурном ОО вряд-ли, пока сам во многом разбираюсь только.

J>Вот реальный пример неудобства, который, имхо, структурной типизацией не решается, ибо интерфейс у всех числовых типов в принципе одинаковый, независимо от смысла: http://www.rsdn.ru/forum/cpp/4266827.1.aspx
Автор: B0FEE664
Дата: 11.05.11


Структурной типизацией как раз и решаются, ведь те же алгебраические типы данных структурно типизированы, хоть и жестко ограниченны.
Но в том же OCaml есть полиморфные варианты в которых как раз и сняты ограничения. На них проблема из твоей ссылки решается так вместо
int используем вариантные `ImageIndex nIndex of int, `PixelIndex nPixel of int, `Milliseconds nMilliseconds of int и теперь добраться до их
значений можно только через паттерн матчинг и перепутать никак ни получится.


FR>>А типобезопасность в структурном ОО никак ни меньше чем в номинативном, просто не стоит забывать что

FR>>типы там образуются по разному.
J>Ну да, и в результате куча типов неожиданно оказываются подходящими. Где безопасность?

А это ортогонально типобезопасности вообще-то.

FR>>Нет я предлагаю плясать не от мифических в случае структурной типизации классов а от объектов и методов.

J>У абсолютно разных и несовместимых по смыслу объектов могут быть одинаковые по сигнатурам и разные по смыслу методы, с этим-то ты согласен?
J>Причем даже если их нет сейчас, они могут появиться завтра, потому что сосед-программер добавил новый метод.
J>Как мне теперь сделать так, чтоб компилятор несовместимые объекты не пропустил и дал ошибку компиляции?

Никак. Если у объектов все сигнатуры методов совпадают то тип этих объектов считается одинаковым.
Ограничить принимаемые объекты при этом вполне возможно, например функция let f (o : my_object) = ...
будет принимать только объекты полностью структурно совпадающие с my_object. Это позволяет эмулировать
номинальный ОО добавляя фейковые методы типа method my_object_id = ()

FR>>В питоне с декораторами этот же подход тоже вполне себе прекрасно работает, при еще большей размытости.

J>Отсюда следует вывод, что размытость не имеет физического смысла, раз все прекрасно работает



FR>>>>Разница как-раз в возможностях статического контроля. Для структурной он не теряется.

J>>>А в шаблонах он теряется, что ли?
FR>>Частично да, просто в подстановочной модели это по моему неизбежно. Тот же SFINAE как пример.
J>И где тут что теряется? Можно пример?

В общем тут теряюсь я
Ладно попытаюсь по другому сформулировать: сам шаблон (при не частичной специализации) работает с неизвестным типом
(понятно что концепты или D'шный Template Constraints это чуть улучшают), отсюда вытекает что мы не можем до подстановки
применять жесткую типизацию. В структурной же тип выводится, он известен и типизация всегда жесткая.

FR>>Неинтерсно если как в С++ нужны побочные эффекты шаблонов.

J>Что ты называешь побочными эффектами шаблонов? Частичную специализацию? Возможность заточки под тип? SFINAE? это все прямые эффекты, это то, зачем шаблоны вообще делались. У шаблонов С++ единственный побочный эфект — шаблонное метапрограммирование, но здесь оно не при делах.

Основной побочный эффект исполнение во время компиляции. Из него и мета вытекает и без него и SFINAE не очень то и нужен.

J>То у тебя плохо, что нет неизменяемых данных, то что переменные становятся неизменяемые Ты уж определись


В полноценном ФП языке или должны быть по умолчанию константные значения или хотя бы возможность их явно задать, хотя бы как const
в C++ (лучше как invariant из D) в питоне этого нет. Неизменяемость же переменных в замыкания питона это просто побочный эффект
от реализации, который только мешает в не ленивых языках использовать замыкания.

FR>>Конечно

FR>>Вообще по моему структурный ОО хорош именно как дополнение к другим мощным свойствам языка, например как в OCaml.
J>Тут полностью согласен. На одной структурной типизации нормальной безопасной системы программирования, имхо, не напишешь. Но в качестве приправы — очень даже вкусненько.

На одной структурной сделаешь, на одном структурном ОО типа OCaml'овского согласен нет.
Просто в базе вся типизация в функциональных языках структурная http://newstar.rinet.ru/~goga/tapl/tapl023.html#toc98

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

J>Т.е. программы в любом случае пишутся в терминах типов ("перевести деньги с этого счета на тот"), а не в терминах того, что можно сделать с произвольных объектом ("взять две любые фигни, у которых есть методы add и subtract, и которые принимают третью фигню, отнять третью у первого, добавить третью второму").
J>Стандартная типизация консервативна и закрыта, т.е. то, что явно не объявлено совместимым, совместимым не является, даже если одно — полный копипейст другого. Уже поэтому она гораздо более безопасна и надежна, но ценой гибкости, естественно. А структурная — наоборот: все может быть совместимым, гибкости хоть отбавляй, зато безопасность так себе. Предикатная охватывает оба варианта, так что в зависимости от стиля ее использования можно получить требуемый баланс между безопасностью и гибкостью.

Все так если про структурный ОО.
А если копать глубже ( http://newstar.rinet.ru/~goga/tapl/tapl-toc.html ) то скорее наоборот
Re[13]: Структурная и номанативная типизация
От: dimgel Россия https://github.com/dimgel
Дата: 12.05.11 08:22
Оценка:
Здравствуйте, jazzer, Вы писали:

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


Где можно про неё почитать поподробнее?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.