Нахождение недостающего класса типов "Уменьшить" из статьи "Дерево пальца"
Вчерашний Wikibender, который начался с этого стекового потока на Comonads, закончился в статье MarkCC о Finger Trees.
В статье он широко использует Reduce
тип класс. Он пишет об этом классе типов, как если бы он был очень распространенной и часто используемой библиотекой, но я не могу найти ее по взлому и не могу найти достаточно документации, чтобы действительно понять код.
Может кто-нибудь помочь мне понять, что Reduce
класс типов делает, как (-<)
а также (>-)
операторы работают, а что должен рассказать о коде в статье (скопировано ниже)?
Листинг кода из Finger Trees выполнен правильно (надеюсь):
Листинг 1: объявление экземпляра для Node
instance Reduce Node where
reducer (-<) (Node2 a b) z = a -< (b -< z)
reducer (-<) (Node3 a b c) z = a -< (b -< (c -< z))
reducer (>-) (Node2 b a) = (z >- b) >- a
reducer (>-) (Node3 c b a) = ((z >- c) >- b) >- a
Листинг 2: объявление экземпляра для FingerTree
instance Reduce FingerTree where
reducer (-<) Empty zero = zero
reducer (-<) (Single x) zero = x -< zero
reducer (-<) Deep left mid right zero = left -<' (mid -<'' (right -<' zero))
where (-<') = reducer (-<)
(-<'') = reducer (reducer (-<))
reducel (>-) zero Empty = zero
reducel (>-) zero (Single x) = zero >- x
reducel (>-) zero (Deep left mid right) = ((zero >-' left) >-'' mid) >-' right
where (>-') = reducel (>-)
(>-'') = reducel (reducel (>-))
листинг 3: типы данных
data Node s = Node2 s s | Node3 s s s
data FingerTree a = Empty
| Single a
| Deep (Digit a) (FingerTree (Node a)) (Digit a)
data Digit a = [ a ]
2 ответа
При условии reduce
это общее альтернативное имя для функции "сгиба", я думаю, что это что-то похожее на Foldable
тип класс. Определения экземпляров, похоже, тоже имеют смысл.
Foldable
класс может быть определен с помощью просто foldr
, который имеет тип подписи foldr :: (Foldable t) => (a -> b -> b) -> b -> t a -> b
тогда как reducer
в этом коде, кажется, reducer :: (Reduce t) => (a -> b -> b) -> t a -> b -> b
, За исключением другого порядка аргументов, он должен работать одинаково.
Обратите внимание, что операторы являются просто аргументами функции - вы можете заменить их все на f
или другой аналогичный общий идентификатор. Использование оператора в качестве имени аргумента бинарной функции... немного необычный выбор, но, думаю, он подчеркивает некоторые аспекты структуры сгиба.
Это определено в документе, связанном в статье: Пальцы: простая структура данных общего назначения.
class Reduce f where
reducer :: (a -> b -> b) -> (f a -> b -> b)
reducel :: (b -> a -> b) -> (b -> f a -> b)