Я делаю забавный проект, в котором я пытаюсь переделать некоторые базовые типы данных и концепции из Java. В настоящее время я занимаюсь Итераторами.
Мой подход заключается в следующем:
(1) Перевести интерфейсы в классы типов
(2) Объявить пользовательские типы данных и экземпляры для фактических реализаций
Итак, я создал следующие классы типов:
class Iterator it where
next :: it e -> (it e, e)
hasNext :: it e -> Bool
class Iterable i where
iterator :: Iterator it => i e -> it e
class Iterable c => Collection c where
add :: c e -> e -> c e
Да, я пытаюсь перевести концепцию Итераторов (которая в данном случае представляет собой просто рамку вокруг фактического списка).
Вот моя реализация простого списка:
data LinkedList e = Element e (LinkedList e) | Nil
deriving (Show, Eq)
instance Collection LinkedList where
add Nil e = Element e Nil
add (Element x xs) e = Element x $ add xs e
Я исключил другие функции, такие как удаление, содержит, добавить все для упрощения.
Вот итератор:
data LinkedListIterator e = It (LinkedList e)
instance Iterator LinkedListIterator where
hasNext (It Nil) = False
hasNext (It _) = True
next (It (Element x xs)) = (It xs, x)
Наконец, экземпляр Iterable LinkedList отсутствует. Вот что я делаю:
instance Iterable LinkedList where
iterator list = It list
Функция итератора упаковывает список в LinkedListIterator
и возвращает его. Здесь GHC заявляет об ошибке:
Could not deduce (it ~ LinkedListIterator)
from the context (Iterator it)
bound by the type signature for
iterator :: Iterator it => LinkedList e -> it e
`it' is a rigid type variable bound by
the type signature for
iterator :: Iterator it => LinkedList e -> it e
Expected type: it e
Actual type: LinkedListIterator e
что я не совсем понимаю. Существует экземпляр Iterator для LinkedListIterator, так почему ожидаемый тип "it e" не совместим с фактическим типом "LinkedListIterator e" (который, насколько я понимаю, является итератором e). Что означает тильда (~
)? Что такое переменная жесткого типа?
РЕДАКТИРОВАТЬ: Я изменил название с Translating Java Types into Haskell types: type deduction fail due to rigid type variable
на Returning something from another type class B in function of type class A in Haskell
, так как я считаю, что моя настоящая проблема связана с возвращением что-то типа-класса-B-from-type- проблема класса A в функции итератора.
РЕШЕНИЕ: Благодаря ответам я теперь изменил свой код на версию ниже. Тем не менее, я весело провел время, читая Typeclassopedia и могу только рекомендовать его. Как уже говорилось, нужно изучать идиомы языка haskell.
data Iterator c e = Next (Iterator c e, e) | Empty
deriving (Show, Eq)
next :: Iterator c e -> (Iterator c e, e)
next (Next (i, e)) = (i, e)
hasNext :: Iterator c e -> Bool
hasNext Empty = False
hasNext _ = True
class Iterable i where
iterator :: i e -> Iterator (i e) e
instance Iterable LinkedList where
iterator Nil = Empty
iterator (Element x xs) = Next (iterator xs, x)