Изучай Haskell во имя добра! (Липовача) - страница 111

и >b должны конкретизироваться одним и тем же типом. Если попытаться применить функцию, которая принимает строку и возвращает строку, то >b у нас – строка, а >a – число; это не сработает. Также, когда мы смотрели на тип функции >fmap для типа >Either a, то видели, что первый параметр не изменяется, а второй может быть изменён; первый параметр актуализируется конструктором данных >Left.

Здесь можно продолжить нашу аналогию с коробками, представив часть >Left как пустую коробку, на которой сбоку записано сообщение об ошибке, поясняющее, почему внутри пусто.

Отображения из модуля >Data.Map также можно сделать функтором, потому что они хранят (или не хранят) значения. Для типа >Map k v функция >fmap будет применять функцию >v –> v' на отображении типа >Map k v и возвращать отображение типа >Map>k>v'.

ПРИМЕЧАНИЕ. Обратите внимание: апостроф не имеет специального значения в типах (как не имеет его и в именовании значений). Этот символ используется для обозначения схожих понятий, незначительно отличающихся друг от друга.

Попытайтесь самостоятельно догадаться, как для типа >Map k определён экземпляр класса >Functor!

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

Сорта и немного тип-фу

Конструкторы типов принимают другие типы в качестве параметров для того, чтобы рано или поздно вернуть конкретный тип. Это в некотором смысле напоминает мне функции, которые принимают значения в качестве параметров для того, чтобы вернуть значение. Мы видели, что конструкторы типов могут быть частично применены, так же как и функции (>Either String – это тип, который принимает ещё один тип и возвращает конкретный тип, например, >Either String Int). Это очень интересно. В данном разделе мы рассмотрим формальное определение того, как типы применяются к конструкторам типов. Точно так же мы выясняли, как формально определяется применение значений к функциям по декларациям типов. Вам не обязательно читать этот раздел для того, чтобы продолжить своё волшебное путешествие в страну языка Haskell, и если вы не поймёте, что здесь изложено, – не стоит сильно волноваться. Тем не менее, если вы усвоили содержание данного раздела, это даст вам чёткое понимание системы типов.



Итак, значения, такие как >3,>"ДА" или >takeWhile (функции тоже являются значениями, поскольку мы можем передать их как параметр и т. д.), имеют свой собственный тип. Типы – это нечто вроде маленьких меток, привязанных к значениям, чтобы мы могли строить предположения относительно них. Но и типы имеют свои собственные маленькие меточки, называемые