Связана ли потеря информации потока со структурным подтипом, присущим этому виду полиморфизма?

Структурное подтипирование в потоке может привести к потере информации:

type O = {x: number, y: number};
type P = {x: number, y: number, z: number}

function f(o: O) {
    return o.x * 2, o.y * 2, o;
}

const p: P = {x: 2, y: 3, z: 100};
const r = f(p);

r.z // type error (property not found)

(Этот код ужасен, потому что он выполняет видимые мутации. Он предназначен только для иллюстративных целей.)

Я читал, что полиморфизм строк — это концепция, позволяющая избежать потери информации, не ставя под угрозу безопасность типов.

Есть ли способ добиться того же с полиморфизмом подтипа?

[ИЗМЕНИТЬ]

Чтобы обратиться к более широкой аудитории, я привожу краткое объяснение несколько пугающей терминологии:

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

person Community    schedule 14.09.2017    source источник


Ответы (1)


Из того, что я прочитал о Flowtype, я почти уверен, что проблема заключается в вашей функции.

Если вы сделаете это вместо этого:

function f<T: O>(o: T): T {
  o.x *= 2;
  o.y *= 2;
  return o;
}

r.z; // okay

Это работает из-за ограниченного полиморфизма. Теперь тип тела проверяется в предположении, что T является подтипом O. Кроме того, никакая информация не теряется между сайтами вызова. Подробнее об этом читайте здесь.

Кроме того, я раньше не слышал о полиморфизме строк, поэтому я пошел и посмотрел. При поиске я прочитал несколько вещей, которые, кажется, указывают на то, что полиморфизм строк не является подтипом. 1, 2, 3.

Чтобы расширить этот ответ и пояснить, почему функция OP не работает, но та, которую я предложил, будет работать правильно. Tэто тоже хороший справочник, но он специфичен для Java.

Имея функцию как:

function f(o: O) {
  return o.x * 2, o.y * 2, o;
}

Функция указывает, что она явно ищет объект типа O, а не объект O или разрешенный подтип O. В функции OPs мы понижаем значение параметра o до типа O, а не используем дженерик (это плохо). Правильный способ справиться с этим — использовать дженерики, чтобы указать, что это может быть тип O или подтип O, что можно сделать следующим образом:

function f<T: O> (o: T): T {
  o.x *= 2;
  o.y *= 2;
  return o;
}

Ознакомьтесь с документацией о том, как поток обрабатывает обобщения и как это связано с параметрами функций. , объект и т.д..

Соответствующая часть:

  • #P10#
  • #P11#
person kyle    schedule 14.09.2017
comment
Почему моя функция является проблемой? Он просто полагается на обещание подтипа, который можно передать в подтипе везде, где ожидается его супертип. Ваш совет состоит в том, чтобы вместо этого использовать ограниченный полиморфизм. Что ж, это просто означает, что подтипирование уступает другим формам полиморфизма — по крайней мере, в некоторых случаях и по сложности, необходимой для реализации надежного алгоритма. - person ; 15.09.2017
comment
@ftor Я понимаю, что вы говорите, и кажется, что это должно работать, но с вашей функцией вы говорите, что она явно ищет параметр типа O, а не параметр типа O или подтипа O. Указав, что параметр имеет значение ‹T: O›, вы сообщаете компилятору, что ожидаете параметр, который будет иметь тип O или подтип O. Узнайте, как Java обрабатывает это softwareengineering.stackexchange .com/questions/227918/ - person kyle; 18.09.2017
comment
@ftor Проверьте мой обновленный ответ, так как он лучше объясняет мой предыдущий комментарий и ООП, но в контексте потока. - person kyle; 18.09.2017
comment
+1 за ваши усилия. Я думаю, решающая подсказка на самом деле находится в одном из ваших комментариев. Это подтип. Это объектно-ориентированная концепция, и я пытаюсь судить о ней с точки зрения FP. Лично для меня это неявное преобразование вниз кажется ошибкой в ​​подтипной части системы типов. Что ж, вы показали более надежную альтернативу, которую я бы назвал ограниченными дженериками для структурной типизации. Этот вид полиморфизма имеет для меня гораздо больше смысла, чем структурное подтипирование. - person ; 19.09.2017
comment
Я согласен, что это кажется немного странным в том, как это работает, и вы, вероятно, могли бы возразить, что это можно рассматривать как ошибку. Компилятор, вероятно, должен предупредить вас, когда вы выполняете неявное преобразование вниз, поскольку я чувствую, что стандарты кодирования должны побуждать людей не делать этого. Кроме того, я чувствую, что неявное преобразование вниз может привести к путанице при отладке, как мы видели в вашем примере. Я не вижу проблемы в том, что компилятор просто предупреждает пользователя, но все же успешно компилирует программу. - person kyle; 19.09.2017