module Data.InfiniteTree
( Tree
, mkTree
, root
, left
, right
, branchF
, surreals
, showTree
, showTreeWide
, showTree'
, showWide
, rotateR
, rotateL
) where
import Control.Arrow ((&&&))
import Control.Comonad
data Tree a = forall b. T b (b -> a) (b -> b) (b -> b)
mkTree :: seed -> (seed -> a) -> (seed -> seed) -> (seed -> seed) -> Tree a
mkTree seed v l r = T seed v l r
root :: Tree a -> a
root (T s v _ _) = v s
left :: Tree a -> Tree a
left (T s v l r) = T (l s) v l r
right :: Tree a -> Tree a
right (T s v l r) = T (r s) v l r
instance Functor Tree where
fmap f (T s v l r) = T s (f . v) l r
instance Comonad Tree where
extract = root
extend f (T s v l r) = T s (\s' -> f (T s' v l r)) l r
branchF :: Functor f => f (Tree a) -> Tree (f a)
branchF f = mkTree f (fmap root) (fmap left) (fmap right)
surreals :: Fractional a => Tree a
surreals = mkTree (Nothing, Nothing) avg (fst &&& Just . avg) (Just . avg &&& snd)
where
avg (Nothing, Nothing) = 0
avg (Just x, Nothing) = x + 1
avg (Nothing, Just y) = y 1
avg (Just x, Just y) = (x + y) / 2
showTree :: Show a => Int -> Tree a -> String
showTree = showTreeWide True
showTreeWide :: Show a => Bool -> Int -> Tree a -> String
showTreeWide wide d t = showTree' wide [] [] t d ""
showTree' :: Show a => Bool -> [String] -> [String] -> Tree a -> Int -> ShowS
showTree' _ _ _ _ 0 = id
showTree' _ lbars _ t 1
= showBars lbars . shows (root t) . showString "...\n"
showTree' wide lbars rbars t d
= showTree' wide (withBar rbars) (withEmpty rbars) (right t) (d 1) .
showWide wide rbars .
showBars lbars . shows (root t) . showChar '\n' .
showWide wide lbars .
showTree' wide (withEmpty lbars) (withBar lbars) (left t) (d 1)
showWide :: Bool -> [String] -> ShowS
showWide wide bars
| wide = showString (concat (reverse bars)) . showString "|\n"
| otherwise = id
showBars :: [String] -> ShowS
showBars [] = id
showBars bars = showString (concat (reverse (tail bars))) . showString node
node :: String
node = "+--"
withBar, withEmpty :: [String] -> [String]
withBar bars = "| " :bars
withEmpty bars = " " :bars
data Rot = Zero | One | Two | Three
rotateL :: Tree a -> Tree a
rotateL t' = mkTree (t',Two) n l r
where
n (t,Two) = root (right t)
n (t,One) = root t
n (t,Zero) = root t
n (_,Three) = error "rotateL n Three"
l (t,Two) = (t, One)
l (t,One) = (left t, Zero)
l (t,Zero) = (left t, Zero)
l (_,Three) = error "rotateL l Three"
r (t,Two) = (right (right t), Zero)
r (t,One) = (left (right t), Zero)
r (t,Zero) = (right t, Zero)
r (_,Three) = error "rotateL r Three"
rotateR :: Tree a -> Tree a
rotateR t' = mkTree (t',Two) n l r
where
n (t,Two) = root (left t)
n (t,One) = root t
n (t,Zero) = root t
n (_,Three) = error "rotateR n Three"
l (t,Two) = (left (left t), Zero)
l (t,One) = (right (left t), Zero)
l (t,Zero) = (left t, Zero)
l (_,Three) = error "rotateR l Three"
r (t,Two) = (t, One)
r (t,One) = (right t, Zero)
r (t,Zero) = (right t, Zero)
r (_,Three) = error "rotateR r Three"