Чому функціонери Haskell мають лише похідні типи в цільовій категорії?


12

У Haskell функтор класу типу Functor визначається наступним чином (див., Наприклад, вікі Haskell ):

class Functor (f :: * -> *) where
  fmap :: (a -> b) -> f a -> f b 

Наскільки я розумію (будь ласка , поправте мене , якщо я помиляюся), такий функтор може мати тільки цільову категорію категорія , побудовану з використанням конструктора типу, наприклад [], Maybeі т.д. З іншого боку, можна думати про функтором , що мають які - або категорії як ціль функтора, наприклад категорія всіх типів Haskell. Наприклад, Intможе бути об'єктом у цільовій категорії функтора, а не просто Maybe Intабо [Int].

Яка мотивація цього обмеження для функторів Haskell?


4
Простота? У Haskell немає функцій першого класу, тому всі функції - це лише конструктори типу.
Даніель Грацер

2
@jozefg: Пробачте моє незнання: що таке "функції першого класу"?
Джорджіо

4
Тож у цій функції ми обманюємо якесь fправо? І у вашому сценарії fмає бути як нормальна функція Haskell і типів карт на типи. У Haskell єдині речі, яким дозволено мати такий вид, - * -> *це конструктори типів. Сімейства типів є більш загальними, але їх завжди потрібно застосовувати повністю
Даніель Гратцер


@jozefg: Іноді я знову і знову думаю про це питання. Я припускаю, що обмеження Хаскелла не впливає на виразну силу функторів. Наприклад, припустимо, що у нас є функтор, який є ізоморфним для функтора списку, але не відображає, скажімо, Int -> [Int], а Int -> <фантазійний тип, не використовуючи конструктор типу>. Тоді я здогадуюсь, що можна довести, що <фантазійний тип, що не використовує конструктор типу>, є ізоморфним для [Int]. Тому вибір об’єктів, визначених за допомогою конструктора типу, просто зручний і не приносить шкоди виразності.
Джорджіо

Відповіді:


1

Взагалі немає обмежень! Коли я почав вивчати теоретико-теоретичну основу для конструкторів типів, ця думка також бентежила мене. Ми доберемось до цього. Але спочатку дозвольте мені вияснити деяку плутанину. Ці дві цитати:

такий функтор може мати як цільову категорію категорію, побудовану за допомогою конструктора типів

і

можна подумати про функторів, які мають будь-яку категорію як ціль функтора, наприклад, категорію всіх типів Haskell

покажіть, що ви нерозумієте, що таке функтор (або, принаймні, ви зловживаєте термінологією).

Функціонери не будують категорії. Функтор - це відображення між категоріями. Функціонери приводять об'єкти та морфізми (типи та функції) у категорію джерела до об'єкта та морфізми в цільовій категорії.

Зауважте, що це означає, що функтор - це дійсно пара відображень: відображення на об'єктах F_obj та відображення на морфізмах F_morph . У Haskell об'єктною частиною F_obj функтора є ім'я конструктора типів (наприклад List), тоді як частина морфізму - це функція fmap(саме від компілятора Haskell слід розібратися, до якого fmapми маємо на увазі будь-який вираз). Таким чином, ми не можемо сказати, що Listце функтор; тільки комбінація Listі fmapє функтором. Все-таки люди зловживають позначеннями; програмісти називають Listфунктора, тоді як теоретики категорії використовують один і той же символ для позначення обох частин функтора.

Крім того, в програмуванні майже всі функтори є ендофайнерами , тобто категорія джерела та цілі однакові - категорія всіх типів нашої мови. Назвемо цю категорію Тип . Ендофунктор F на Type вказує тип T на інший тип FT і функцію T -> S на іншу функцію FT -> FS . Звичайно, це відображення повинне підкорятися законам функтора.

Використовуючи в Listякості прикладу: у нас є конструктор типу List : Type -> Type, і функція fmap: (a -> b) -> (List a -> List b), що разом утворює функтор. Т

Є ще один заключний момент, який слід прояснити. Запис List intне створює новий тип списків цілих чисел. Цей тип вже існував . Це був об’єкт у нашій категорії Тип . List Intце просто спосіб посилатися на це.

Тепер вам цікаво, чому функтор не може відобразити тип, скажімо, Intабо String. Але, може! Потрібно просто використовувати функцію посвідчення особи. Для будь-якої категорії С функціонер ідентичності відображає кожен об'єкт до себе і морфізм до себе. Нескладно переконатися, що це відображення відповідає законам функтора. У Haskell це буде конструктор типів, id : * -> *який відображає кожен тип до себе. Наприклад, id intоцінює до int.

Крім того, можна навіть створити постійні функтори, які зіставляють всі типи в один тип. Наприклад, функтор ToInt : * -> *, де ToInt a = intдля всіх типів a, і відображає всі морфізми до цілої функції ідентичності: fmap f = \x -> x


Дякуємо за вашу відповідь, це питання вже понад два роки. "Функціонери не будують категорії.": Я цього не говорив. Я сказав, що функтори відображають дві категорії, де цільова категорія повинна мати форму f a, де f, наскільки я знаю, конструктор типу. З того, що я пам’ятаю з теорії категорій, це повинно бути якесь канонічне подання (початковий об’єкт у категорії категорій? Можливо, я зловживаю термінологією.) У будь-якому разі я уважно прочитаю вашу відповідь. Дуже дякую.
Джорджіо

@Giorgio отак, я не помітив, скільки років було ха-ха. Він просто виявився у "питаннях без відповіді". Я не впевнений, що ви маєте на увазі під "канонічним поданням". Наскільки я знаю (і я можу помилятися тут), між функторами та початковими / кінцевими об'єктами немає зв’язку.
садок

Я маю на увазі це: en.wikipedia.org/wiki/Initial_algebra (див. Використання в інформатиці). У Хаскеллі (більшість) функторів визначені алгебраїчні типи даних. Цільовим об'єктом такого функтора є початкова алгебра. Початкова алгебра ізоморфна набору термінів, побудованих за допомогою конструкторів значень. Наприклад, для списків []і :. Я мав на увазі це канонічним поданням.
Джорджо

Так, я знаю, що таке початковий об'єкт, і що індуктивні типи даних є початковими об'єктами у F-алгебрі категорії. Ви вірні, що багато конструкторів типів визначаються індуктивно. Але це суворо не потрібно. Наприклад, функтор, (_, int)який приймає тип aдо типу продукту (a, int)і функція f : 'a -> 'bдо g : 'a * int -> 'a * int, не є індуктивним.
садівник

Можливо , ви мали в виду: «бере ... функцію , f : 'a -> 'bщоб g : 'a * int -> 'b * int?
Giorgio
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.