Можно ли использовать universeBi uniplate для получения узлов в первую очередь?

Можно ли использовать Uniplate's universeBiполучить вывод в порядке ширины? Похоже, что результаты возвращаются в первую очередь в глубину. Мне интересно, как я могу использовать uniplate для полученияuniverseBi в широком смысле.

Для иллюстрации рассмотрим следующую игрушечную программу:

{-# LANGUAGE DeriveDataTypeable #-}

import Data.Data
import Data.Generics.Uniplate.Data

data A = A B Int deriving (Data, Typeable)
data B = B Int   deriving (Data, Typeable)

val :: A
val = A (B 1) 2

ints :: [Int]
ints = universeBi val

Я получил:

*Main> ints
[1,2]

Но это прежде всего в глубину, так как 1 получается из Bузел. Я бы предпочел получить его в порядке возрастания, т.е. получить[2,1]. Возможно ли это в униплате?

1 ответ

Решение

Вы можете покопаться в структуре Str вернулся biplate:

layers :: Str a -> [[a]]
layers Zero = []
layers (One x) = [[x]]
layers (Two f x) = catLayers (layers f) ([] : layers x)
  where catLayers [] ys = ys
        catLayers xs [] = xs
        catLayers (x : xs) (y : ys) = (x ++ y) : catLayers xs ys
layersBi :: Biplate from to => from -> [[to]]
layersBi = layers . fst . biplate
breadthBi :: Biplate from to => from -> [to]
breadthBi = concat . layersBi

А сейчас

breadthBi (A (B 1) 2) :: [Int]
-- = [2, 1]

а также

data Tree a = Branch (Tree a) a (Tree a) | Leaf deriving (Data, Typeable)
--       4
--   2       6
-- 1   3   5   7
example = Branch (Branch (Branch Leaf 1 Leaf) 2 (Branch Leaf 3 Leaf)) 4 (Branch (Branch Leaf 5 Leaf) 6 (Branch Leaf 7 Leaf))
(layersBi :: Data a => Tree a -> [[a]]) example
-- = [[],[4],[2,6],[1,3,5,7]]

Я не уверен, действительно ли это гарантировано Strточно отражает структуру типа данных, но похоже. Вместо этого вы можете приготовить что-нибудь изData примитивы, если нужно.

Другие вопросы по тегам