Я относительно новичок в Haskell, и я считаю, что я неправильно понимаю что-то фундаментальное в классах классов. Предположим, я хотел бы создать класс типа 'T', реализующий n-арные деревья, поддерживаемые четырьмя алгебраическими типами A, B, C и D, структура которых налагает максимальную глубину в четыре. Это кажется глупым примером, но я думаю, что это лучше всего иллюстрирует мою мысль.
module Test where
class T t0 where
parent :: T t1 => t0 -> Maybe t1
children :: T t1 => t0 -> [t1]
data A = A [B]
instance T A where
parent (A _) = Nothing
children (A bs) = bs
data B = B A [C]
instance T B where
parent (B a _) = Just a
children (B _ cs) = cs
data C = C B [D]
instance T C where
parent (C b _) = Just b
children (C _ ds) = ds
data D = D C
instance T D where
parent (D c) = Just c
children (D _) = []
Я бы хотел написать общие родительские и дочерние функции, но GHC не имеет ни одного из них.
Test.hs:10:27:
Could not deduce (t1 ~ B)
from the context (T t1)
bound by the type signature for children :: T t1 => A -> [t1]
at Test.hs:10:9-28
`t1' is a rigid type variable bound by
the type signature for children :: T t1 => A -> [t1]
at Test.hs:10:9
Expected type: [t1]
Actual type: [B]
In the expression: bs
In an equation for `children': children (A bs) = bs
In the instance declaration for `T A'
Test.hs:14:31:
Could not deduce (t1 ~ A)
from the context (T t1)
bound by the type signature for parent :: T t1 => B -> Maybe t1
at Test.hs:14:9-31
`t1' is a rigid type variable bound by
the type signature for parent :: T t1 => B -> Maybe t1
at Test.hs:14:9
In the first argument of `Just', namely `a'
In the expression: Just a
In an equation for `parent': parent (B a _) = Just a
Test.hs:15:29:
Could not deduce (t1 ~ C)
from the context (T t1)
bound by the type signature for children :: T t1 => B -> [t1]
at Test.hs:15:9-30
`t1' is a rigid type variable bound by
the type signature for children :: T t1 => B -> [t1]
at Test.hs:15:9
Expected type: [t1]
Actual type: [C]
In the expression: cs
In an equation for `children': children (B _ cs) = cs
In the instance declaration for `T B'
Test.hs:19:31:
Could not deduce (t1 ~ B)
from the context (T t1)
bound by the type signature for parent :: T t1 => C -> Maybe t1
at Test.hs:19:9-31
`t1' is a rigid type variable bound by
the type signature for parent :: T t1 => C -> Maybe t1
at Test.hs:19:9
In the first argument of `Just', namely `b'
In the expression: Just b
In an equation for `parent': parent (C b _) = Just bv
Я (думаю, я) понимаю, что классы классов совсем не похожи на интерфейсы Java, поскольку функции уровня класса должны работать для любого возможного значения предоставленных переменных типа; вызывающий абонент не "решает" тип. Я не понимаю, почему GHC не может вывести (t1 ~ _), потому что тип, замененный на t1, всегда является экземпляром "T". Я вижу, что существует некоторая циклическая зависимость между объявлениями экземпляра, например. Объявление экземпляра зависит от того, насколько B действителен, что зависит от A и C и т.д., Но я чувствую, что GHC достаточно умен, чтобы понять это, и я просто что-то пропустил. Я всегда получаю эту ошибку всякий раз, когда мне хочется, чтобы функция класса типа принимала один тип в классе, но возвращала другую... Есть ли способ выполнить это с помощью классов классов?
Я вижу, что здесь есть много похожих вопросов, но мне еще предстоит найти тот, который соответствует моей проблеме (насколько я могу судить).
Спасибо заранее.