Я все еще работаю над своим текстовым редактором Rasa.
На данный момент я создаю систему для отслеживания окон / разделений (аналогично разделам в vim). Мне показалось естественным представить эту структуру в виде дерева:
data Dir = Hor
| Vert
deriving (Show)
data Window a =
Split Dir SplitInfo (Window a) (Window a)
| Single ViewInfo a
deriving (Show, Functor, Traversable, Foldable)
Это отлично работает, я сохраняю свои View
в дереве, а затем могу перемещаться по ним / fmap, чтобы изменить их, это также хорошо согласуется с пакетом линз!
В последнее время я узнал о схемах рекурсии, и мне кажется, как будто это подходящий вариант использования для них, поскольку дерево является рекурсивной структурой данных.
Мне удалось понять это достаточно хорошо, чтобы построить версию Fixpoint:
data WindowF a r =
Split Dir SplitInfo r r
| Single ViewInfo a
deriving (Show, Functor)
type Window a = Fix (WindowF a)
Однако теперь экземпляр Functor используется r
;
Я пробовал несколько вариантов
deriving instance Functor Window
Но это задыхается, потому что окно - это синоним типа.
И:
newtype Window a = Window (Fix (WindowF a)) deriving Functor
И это тоже не удается;
• Couldn't match kind ‘* -> *’ with ‘*’
arising from the first field of ‘Window’ (type ‘Fix (WindowF a)’)
• When deriving the instance for (Functor Window)
- Можно ли еще определить fmap / traverse для
a
? Или мне нужно выполнить эти операции с помощью примитивов схем рекурсии? Могу ли я реализовать Бифунктор? Как будет выглядеть реализация экземпляра?
Остальные типы: здесь, проект не компилируется, потому что у меня нет подходящего экземпляра Functor для Window ...
Спасибо!!