Я пытаюсь прочитать исходный код пакета Haskell Data.List.Class. (Список -0.4.2 ). Но я застрял с некоторым синтаксисом.
В самом начале написано:
data ListItem l a =
Nil |
Cons { headL :: a, tailL :: l a }
Я не знаком с синтаксисом 3-й строки. Я предполагаю, что эта последняя строка эквивалентна Cons a (l a)
??. Но я не совсем уверен. Я заметил, что в заголовке файла указано:{-# LANGUAGE FlexibleContexts, TypeFamilies #-}
.
Затем, когда я продолжаю, есть странное использование утверждения type
:type ItemM l :: * -> *
, чего я не мог понять.
Data.List.Class
-- | A class for list types. Every list has an underlying monad.
class (MonadPlus l, Monad (ItemM l)) => List l where
type ItemM l :: * -> *
runList :: l a -> ItemM l (ListItem l a)
joinL :: ItemM l (l a) -> l a
cons :: a -> l a -> l a
cons = mplus. return
Может ли кто-нибудь помочь объяснить, что они означают? У меня есть прекрасное понимание Data.List, но эта вещь с классом типов мне не совсем ясна. Также я искал вики, примеры и/или учебные пособия по использованию Data.List.{Class,Tree}, но, похоже, их нет, кроме комментариев, которые идут с кодом. Любые указатели здесь?
Спасибо.
--обновление --Первый ответ (@Chris )помог мне понять подпись Kind и синтаксис записи, что действительно полезно. Однако я до сих пор не могу разобраться в этом фрагменте кода в целом с точки зрения того, как он фиксирует/определяет поведение списка и какое значение он добавляет к знакомым определениям Data.List. Вот некоторые дополнительные детали, где есть только два оператора экземпляра. Также термин Identity
происходит от import Data.Functor.Identity (Identity(..))
. Не могли бы вы помочь объяснить, что делает этот класс типов, чтобы зафиксировать характеристики списка, как мы его обычно знаем? Опять же, я искал его в Интернете, но на самом деле нет документации для Data.List.Class, кроме самого кода. Кто-нибудь знает?
Кроме того, есть ли другой пример использования оператора type
в ограничении класса типов, аналогичный тому, что в этом примере? Я искал на сайте Learnyouahaskell.com/ (@Landei ), но такого примера не нашел. Я предполагаю, что использование type
здесь похоже на то, как вы использовали бы typedef
в шаблонах C++ для определения «функций по типам», верно?
Спасибо еще раз.
instance List [] where
type ItemM [] = Identity
runList [] = Identity Nil
runList (x:xs) = Identity $ Cons x xs
joinL = runIdentity
cons = (:)
instance Functor m => Functor (ListItem m) where
fmap _ Nil = Nil
fmap func (Cons x xs) = Cons (func x) (fmap func xs)