1 {-# LANGUAGE FlexibleInstances #-}
2 {-# LANGUAGE OverloadedStrings #-}
3 module Data.TreeSeq.Strict where
5 import Control.Applicative (Applicative(..))
6 import Control.Monad (Monad(..))
8 import Data.Eq (Eq(..))
9 import Data.Foldable (Foldable(..))
10 import Data.Function (($), (.))
11 import Data.Functor (Functor(..), (<$>))
12 import Data.Monoid (Monoid(..))
13 import Data.Ord (Ord(..))
14 import Data.Semigroup (Semigroup(..))
15 import Data.Sequence (Seq, ViewL(..))
16 import Data.Traversable (Traversable(..))
17 import Text.Show (Show(..))
18 import qualified Data.List as List
19 import qualified Data.Sequence as Seq
20 import qualified Data.Text.Lazy as TL
25 , subTrees :: !(Trees a)
27 deriving (Eq, Ord, Show)
28 instance Functor Tree where
29 fmap f (Tree a ts) = Tree (f a) (fmap (fmap f) ts)
30 instance Applicative Tree where
31 pure a = Tree a mempty
32 Tree f tfs <*> ta@(Tree a tas) =
33 Tree (f a) (fmap (f <$>) tas <> fmap (<*> ta) tfs)
34 instance Monad Tree where
37 Tree a' (ts' <> fmap (>>= f) ts)
38 where Tree a' ts' = f a
39 instance Foldable Tree where
40 foldMap f (Tree a ts) = f a `mappend` foldMap (foldMap f) ts
41 instance Traversable Tree where
42 traverse f (Tree a ts) = Tree <$> f a <*> traverse (traverse f) ts
43 sequenceA (Tree a ts) = Tree <$> a <*> traverse sequenceA ts
46 tree0 a = Tree a mempty
48 isTree0 :: Tree a -> Bool
49 isTree0 (Tree _ ts) = null ts
51 isTreeN :: Tree a -> Bool
52 isTreeN (Tree _ ts) = not (null ts)
55 type Trees a = Seq (Tree a)
58 newtype Pretty a = Pretty a
59 instance Show a => Show (Pretty (Trees a)) where
60 show (Pretty t) = TL.unpack $ prettyTrees t
61 instance Show a => Show (Pretty (Tree a)) where
62 show (Pretty t) = TL.unpack $ prettyTree t
64 prettyTree :: Show a => Tree a -> TL.Text
65 prettyTree = TL.unlines . pretty
67 prettyTrees :: Show a => Trees a -> TL.Text
68 prettyTrees = foldr (\t acc -> prettyTree t <> "\n" <> acc) ""
70 pretty :: Show a => Tree a -> [TL.Text]
71 pretty (Tree a ts0) = TL.pack (show a) : prettySubTrees ts0
76 t:<ts | Seq.null ts -> "|" : shift "`- " " " (pretty t)
77 | otherwise -> "|" : shift "+- " "| " (pretty t) <> prettySubTrees ts
78 shift first other = List.zipWith (<>) (first : List.repeat other)