{-# LANGUAGE TupleSections #-} {-# LANGUAGE GADTs, NoImplicitPrelude, UnicodeSyntax #-} module Data.Nested.Internal ( -- * Tree and Forest types Tree, Forest -- * Query , fruit, forest, trees, treeAssocs , nullTree, nullForest , sizeTree, sizeForest , lookupTree, lookupForest , memberTree, memberForest -- * Construction , emptyTree, emptyForest , singletonTree, singletonForest , fromFoldableTree, fromFoldableForest -- * List , toListForest, toListTree , fromListTree, fromListForest ) where import qualified Data.List as L import Prelude.Unicode ((⊥)) import Prelude (Num, (+)) import Data.Maybe (Maybe(Just, Nothing), maybe, isJust) import Data.Int (Int) import Data.Bool (Bool, otherwise) import Data.Ord (Ord) import Data.Tuple (uncurry, snd) import Data.Function (flip, ($), const, id) import Data.Function.Unicode ((∘)) import Data.Functor (Functor, fmap, (<$>)) import Data.Foldable (Foldable, foldr, foldMap) import Data.Traversable (Traversable, mapAccumL, traverse) import Data.Monoid (Monoid, mempty, mappend, mconcat) import Data.Monoid.Unicode ((⊕)) import Text.Show (Show) import Control.Arrow ((&&&)) import Control.Monad (MonadPlus, (>>=), join, return, mplus) import Control.Applicative (Applicative) import Control.Applicative.Unicode ((⊛)) import Data.Map (Map) import qualified Data.Map as M data Tree κ α where Tree ∷ { fruit ∷ α , forest ∷ Forest κ α } → Tree κ α deriving (Show) data Forest κ α where Forest ∷ { unForest ∷ Map κ (Tree κ α) } → Forest κ α deriving (Show) instance Functor (Forest κ) where fmap f = Forest ∘ ((f <$>) <$>) ∘ unForest instance Functor (Tree κ) where fmap f (Tree v ts) = Tree (f v) (f <$> ts) instance (Ord κ, Monoid α) ⇒ Monoid (Forest κ α) where mempty = emptyForest mappend = unionForestWith (⊕) instance (Ord κ, Monoid α) ⇒ Monoid (Tree κ α) where mempty = Tree mempty mempty t1 `mappend` t2 = Tree (fruit t1 ⊕ fruit t2) (forest t1 ⊕ forest t2) instance Foldable (Forest κ) where foldMap f = foldMap (foldMap f) ∘ unForest foldr f z = foldr (flip $ foldr f) z ∘ unForest instance Foldable (Tree κ) where foldMap f = (f ∘ fruit) ⊕ (foldMap f ∘ forest) foldr f z (Tree v ts) = f v (foldr f z ts) instance Traversable (Forest κ) where traverse f = (Forest <$>) <$> traverse (traverse f) ∘ unForest instance Traversable (Tree κ) where traverse f (Tree v ts) = Tree <$> f v ⊛ traverse f ts nullForest ∷ Forest κ α → Bool nullForest = M.null ∘ unForest nullTree ∷ Tree κ α → Bool nullTree = nullForest ∘ forest trees ∷ Forest κ α → [Tree κ α] trees = M.elems ∘ unForest treeAssocs ∷ Forest κ α → [(κ, Tree κ α)] treeAssocs = M.assocs ∘ unForest sizeForest ∷ Forest κ α → Int sizeForest = foldr (const (+1)) 0 sizeTree ∷ Tree κ α → Int sizeTree = (+1) ∘ sizeForest ∘ forest -- a more general version would use Folable φ as input and a user-specifiable Monoid output lookupForest ∷ (Traversable φ, Ord κ) ⇒ Forest κ α → φ κ → φ (Maybe α) lookupForest f = snd ∘ mapAccumL (flip lookup) (Just f) where lookup ∷ Ord κ ⇒ κ → Maybe (Forest κ α) → (Maybe (Forest κ α), Maybe α) lookup k = (fmap forest &&& fmap fruit) ∘ join ∘ fmap (M.lookup k ∘ unForest) lookupTree ∷ (Traversable φ, Ord κ) ⇒ Tree κ α → φ κ → (α, φ (Maybe α)) lookupTree t = (fruit t,) ∘ lookupForest (forest t) memberTree ∷ (Traversable φ, Ord κ) ⇒ Tree κ α → φ κ → φ Bool memberTree t = (isJust <$>) ∘ snd ∘ lookupTree t memberForest ∷ (Traversable φ, Ord κ) ⇒ Forest κ α → φ κ → φ Bool memberForest f = (isJust <$>) ∘ lookupForest f emptyForest ∷ Forest κ α emptyForest = Forest M.empty emptyTree ∷ α → Tree κ α emptyTree v = Tree v emptyForest singletonForest ∷ Foldable φ ⇒ φ (κ,α) → Forest κ α singletonForest = foldr (uncurry singleton) emptyForest where singleton k v = Forest ∘ M.singleton k ∘ Tree v singletonTree ∷ Foldable φ ⇒ α → φ (κ,α) → Tree κ α singletonTree x = Tree x ∘ singletonForest fromFoldableForest ∷ (Foldable φ, Foldable ψ, Ord κ) ⇒ ψ (φ (κ, α)) → Forest κ α fromFoldableForest = foldr (unionForest ∘ singletonForest) emptyForest fromFoldableTree ∷ (Foldable φ, Foldable ψ, Ord κ) ⇒ α → ψ (φ (κ, α)) → Tree κ α fromFoldableTree x = Tree x ∘ fromFoldableForest fromListForest ∷ Ord κ ⇒ [[(κ, α)]] → Forest κ α fromListForest = fromFoldableForest fromListTree ∷ Ord κ ⇒ α → [[(κ, α)]] → Tree κ α fromListTree = fromFoldableTree toListForest ∷ Forest κ α → [[(κ, α)]] toListForest = fmap L.reverse ∘ foldrForestWithAncestorsAndLeafMarker leafCons [] where leafCons b = if b then (:) else flip const toListTree ∷ Tree κ α → (α, [[(κ, α)]]) toListTree t = (fruit t, toListForest (forest t)) unionForest ∷ Ord κ ⇒ Forest κ α → Forest κ α → Forest κ α unionForest (Forest f1) (Forest f2) = Forest $ M.unionWith unionTree f1 f2 unionTree ∷ Ord κ ⇒ Tree κ α → Tree κ α → Tree κ α unionTree (Tree _x1 f1) (Tree x2 f2) = Tree x2 (unionForest f1 f2) unionForestWithKey ∷ Ord κ ⇒ (κ → α → α → α) → Forest κ α → Forest κ α → Forest κ α unionForestWithKey f (Forest m1) (Forest m2) = Forest $ M.unionWithKey (unionTreeWithKey' f) m1 m2 unionForestWith ∷ Ord κ ⇒ (α → α → α) → Forest κ α → Forest κ α → Forest κ α unionForestWith f = unionForestWithKey (const f) unionTreeWithKey' ∷ Ord κ ⇒ (κ → α → α → α) → κ → Tree κ α → Tree κ α → Tree κ α unionTreeWithKey' f k t1 t2 = Tree (f k (fruit t1) (fruit t2)) (unionForestWithKey f (forest t1) (forest t2)) unionTreeWithKey ∷ Ord κ ⇒ (α → α → α) → (κ → α → α → α) → Tree κ α → Tree κ α → Tree κ α unionTreeWithKey g f t1 t2 = Tree (g (fruit t1) (fruit t2)) (unionForestWithKey f (forest t1) (forest t2)) unionTreeWith ∷ Ord κ ⇒ (α → α → α) → Tree κ α → Tree κ α → Tree κ α unionTreeWith f = unionTreeWithKey f (const f) foldrForestWithAncestors ∷ ([(κ, α)] → β → β) → β → Forest κ α → β foldrForestWithAncestors f = foldrForestWithAncestors1 f [] foldrForestWithAncestors1 ∷ ([(κ, α)] → β → β) → [(κ, α)] → β → Forest κ α → β foldrForestWithAncestors1 f kvs z = M.foldrWithKey (foldrTreeWithAncestors1 f kvs) z ∘ unForest foldrTreeWithAncestors1 ∷ ([(κ, α)] → β → β) → [(κ, α)] → κ → Tree κ α → β → β foldrTreeWithAncestors1 f kvs k t z = f as (foldrForestWithAncestors1 f as z (forest t)) where as = (k, fruit t):kvs foldrForestWithAncestorsAndLeafMarker ∷ (Bool → [(κ, α)] → β → β) → β → Forest κ α → β foldrForestWithAncestorsAndLeafMarker f = foldrForestWithAncestorsAndLeafMarker1 f [] foldrForestWithAncestorsAndLeafMarker1 ∷ (Bool → [(κ, α)] → β → β) → [(κ, α)] → β → Forest κ α → β foldrForestWithAncestorsAndLeafMarker1 f kvs z = M.foldrWithKey (foldrTreeWithAncestorsAndLeafMarker1 f kvs) z ∘ unForest foldrTreeWithAncestorsAndLeafMarker1 ∷ (Bool → [(κ, α)] → β → β) → [(κ, α)] → κ → Tree κ α → β → β foldrTreeWithAncestorsAndLeafMarker1 f kvs k t z = f isLeaf as (foldrForestWithAncestorsAndLeafMarker1 f as z (forest t)) where as = (k, fruit t):kvs isLeaf = nullTree t