Тема: Коваріянт та контрваріянт
Почиткав трохи про ці речі, і не можу зрозуміти одного прикладу.
Спочатку позначки покажу:
A ≼ B означає, що A є підтипом B.
A → B це така функція, котра приймає аргумент з типом А, та повертає результат з типом B.
x : A означає, що x має тип A.
Уявімо, що у нас є наступні типи
Пундель ≼ Пес ≼ Тварина
тобто Пундель є підтипом Песика, а Песик є підтипом Тварини, ніби все логічно, йдемо від більшого (Тварини), до меншого (Пунделя).
Далі, у нас є така от функція
f : (Пес → Пес) → void
тобто, функція приймає іншу функцію, аргументом котрої є Пес, і котра повертає Песика.
Далі йде питання, яку з наступних чотирьох функцій можна передати в функцію, що я навів вище
Пундель → Пундель
Пундель → Тварина
Тварина → Тварина
Тварина → Пундель
На думку автора статті - четвертий варіянт є правильним Тварина → Пундель.
Пояснює він ось цим:
(Тварина → Пундель) ≼ (Пес → Пес)
Тобто, функція, що приймає Тварину, і повертає Пунделя, є підтипом функції, що приймає і повертає Песика.
Тварина є більш загальною, ніж Пес, але в цьому випадку це зветься контрваріянтом, і воно робе. Тобто, функція може приймати речі вищі по ієрархії наслідування, а повертати може менші.
Але я оце думаю - окей, але якщо Пес ≼ Тварина, то Пес матиме всі функції і властивості Тварини, але також може мати власні, свої.
Якщо ми матимемо ще один підтип Кіт ≼ Тварина, то ми ж зможемо передати його в (Тварина → Пундель), і тоді, всередині (Пес → Пес) ми не матимемо необхідних властивостей, адже будемо очікувати Песика, але отримаємо Котика.