Почему Либо получает Шоу, а может и нет?

Документация обоих Either а также Maybe указывают, что у них есть случаи Show,

Either определяется как производный Show просто:

data  Either a b  =  Left a | Right b
  deriving (Eq, Ord, Read, Show, Typeable)

Еще, Maybe не:

data  Maybe a  =  Nothing | Just a
  deriving (Eq, Ord)

Так как они являются частью base и так похожи, почему не Maybe напрямую выводить Show?

Другой вопрос также может быть, откуда он Show пример?

2 ответа

Решение

Экземпляр для Maybe определяется явно в GHC.Show наряду с примерами для целого ряда других распространенных типов, таких как кортежи. Вы можете узнать, где был определен экземпляр, используя :i команда в ghci:

Prelude> :i Maybe
data Maybe a = Nothing | Just a     -- Defined in ‘Data.Maybe’
instance Eq a => Eq (Maybe a) -- Defined in ‘Data.Maybe’
instance Monad Maybe -- Defined in ‘Data.Maybe’
instance Functor Maybe -- Defined in ‘Data.Maybe’
instance Ord a => Ord (Maybe a) -- Defined in ‘Data.Maybe’
instance Read a => Read (Maybe a) -- Defined in ‘GHC.Read’
instance Show a => Show (Maybe a) -- Defined in ‘GHC.Show’

Я не знаю, почему они определили экземпляр явно или поместили его в GHC.Show вместо Data.Maybe - насколько я могу судить, его можно перенести в Data.Maybe и / или производные. Я думаю, что они не хотели Data.Maybe зависеть ни от чего, кроме GHC.Base (как это происходит сейчас), предположительно потому, что он используется в некоторых других основных модулях.

Кортежи AFAIK нигде не определены, поэтому во избежание появления осиротевших экземпляров [1] экземпляры Show для кортежей должны быть определены в GHC.Show[2]. Реализация этих случаев происходит с использованием foldr1:

show_tuple :: [ShowS] -> ShowS
show_tuple ss = showChar '('
              . foldr1 (\s r -> s . showChar ',' . r) ss
              . showChar ')'

поэтому GHC.Show импортирует GHC.List, где определена эта функция. GHC.List, в свою очередь, определяет lookup, который находится в Maybe монада (уклон мономорфизма старого доброго старого Haskell 98, я думаю). Таким образом, GHC.List импортирует Data.Maybe. Для того, чтобы определить Show Например, Data.Maybe необходимо импортировать GHC.Show (прямо или косвенно), что сделает всю последовательность GHC.Show -> GHC.List -> Data.Maybe -> GHC.Show циклической зависимостью. GHC не очень хорошо поддерживает циклические зависимости (не потому, что их легко поддерживать!), Поэтому base работает очень усердно, чтобы их избежать.

[1] Экземпляр-сирота - это экземпляр, определенный в другом модуле, нежели класс и тип, участвующий в экземпляре. Формально, Haskell требует, чтобы поиск экземпляров выполнялся в любом модуле, прямо или косвенно импортированном компилируемым модулем; но для не сиротских случаев GHC может замкнуть это и просто посмотреть в двух местах. Для бесхозных экземпляров он должен отслеживать каждый потерянный экземпляр в модуле, а затем отслеживать, что эти экземпляры повторно открываются каждым модулем, который их импортирует, что является более дорогостоящим (и означает, что он должен поддерживать контекстную среду с потенциально большим количеством экземпляров, которые даже не относятся к текущему модулю, потому что он фактически не импортирует эти классы или типы). Поэтому хорошей практикой является избегать случаев осиротения по этой причине.

Несколько более философски, сиротские экземпляры - действительно хороший способ получить два конфликтующих экземпляра одного и того же класса / типа в вашей программе, так как они оба "видимы" в вашей программе. Main Модуль означает, что они будут конфликтовать. Так что языковая особенность сама по себе довольно хитрая.

[2] IIRC GHC предоставляет только Show экземпляры вплоть до (относительно небольшого) фиксированного числа компонентов кортежей, которые не совсем соответствуют Haskell 98, но достаточно хороши для любых практических задач программирования. (Серьезно, в любом случае, не используйте кортежи с более чем 3 элементами, вы забудете, что означают конкретные компоненты). Я не знаю, был ли обновлен стандарт, чтобы привести GHC в соответствие за последние несколько лет или нет.

Другие вопросы по тегам