{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeFamilies #-}
module Data.RAVec.Tree (
Tree (..),
singleton,
toList,
(!),
tabulate,
leftmost,
rightmost,
foldMap,
foldMap1,
ifoldMap,
ifoldMap1,
foldr,
ifoldr,
foldr1Map,
ifoldr1Map,
foldl,
ifoldl,
length,
map,
imap,
traverse,
itraverse,
#ifdef MIN_VERSION_semigroupoids
traverse1,
itraverse1,
#endif
zipWith,
izipWith,
repeat,
universe,
liftArbitrary,
liftShrink,
) where
import Prelude
(Bool (..), Eq (..), Functor (..), Int, Ord (..), Show, id, seq,
uncurry, ($), (*), (.))
import Control.Applicative (Applicative (..), (<$>))
import Control.DeepSeq (NFData (..))
import Data.Hashable (Hashable (..))
import Data.Monoid (Monoid (..))
import Data.Nat (Nat (..))
import Data.Semigroup (Semigroup (..))
import Data.Typeable (Typeable)
import Data.Wrd (Wrd (..))
import qualified Data.Type.Nat as N
import qualified Data.Foldable as I (Foldable (..))
import qualified Data.Traversable as I (Traversable (..))
import qualified Test.QuickCheck as QC
#ifdef MIN_VERSION_distributive
import qualified Data.Distributive as I (Distributive (..))
#ifdef MIN_VERSION_adjunctions
import qualified Data.Functor.Rep as I (Representable (..))
#endif
#endif
#ifdef MIN_VERSION_semigroupoids
import Data.Functor.Apply (Apply (..))
import qualified Data.Semigroup.Foldable as I (Foldable1 (..))
import qualified Data.Semigroup.Traversable as I (Traversable1 (..))
#endif
data Tree (n :: Nat) a where
Leaf :: a -> Tree 'Z a
Node :: Tree n a -> Tree n a -> Tree ('S n) a
deriving (Typeable)
goLeft :: (Wrd ('S n) -> a) -> Wrd n -> a
goLeft f xs = f (W0 xs)
goRight :: (Wrd ('S n) -> a) -> Wrd n -> a
goRight f xs = f (W1 xs)
deriving instance Eq a => Eq (Tree n a)
deriving instance Ord a => Ord (Tree n a)
deriving instance Show a => Show (Tree n a)
instance Functor (Tree n) where
fmap = map
instance I.Foldable (Tree n) where
foldMap = foldMap
foldr = foldr
foldl = foldl
#if MIN_VERSION_base(4,8,0)
null _ = False
toList = toList
length = length
#endif
instance I.Traversable (Tree n) where
traverse = traverse
#ifdef MIN_VERSION_semigroupoids
instance I.Foldable1 (Tree n) where
foldMap1 = foldMap1
instance I.Traversable1 (Tree n) where
traverse1 = traverse1
#endif
instance NFData a => NFData (Tree n a) where
rnf (Leaf x) = rnf x
rnf (Node x y) = rnf x `seq` rnf y
instance Hashable a => Hashable (Tree n a) where
hashWithSalt salt (Leaf x) = salt
`hashWithSalt` x
hashWithSalt salt (Node x y) = salt
`hashWithSalt` x
`hashWithSalt` y
instance N.SNatI n => Applicative (Tree n) where
pure = repeat
(<*>) = zipWith ($)
x <* _ = x
_ *> x = x
#if MIN_VERSION_base(4,10,0)
liftA2 = zipWith
#endif
#ifdef MIN_VERSION_distributive
instance N.SNatI n => I.Distributive (Tree n) where
distribute f = tabulate (\k -> fmap (! k) f)
#ifdef MIN_VERSION_adjunctions
instance N.SNatI n => I.Representable (Tree n) where
type Rep (Tree n) = Wrd n
tabulate = tabulate
index = (!)
#endif
#endif
instance Semigroup a => Semigroup (Tree n a) where
Leaf x <> Leaf y = Leaf (x <> y)
Node x y <> Node u v = Node (x <> u) (y <> v)
#ifdef MIN_VERSION_semigroupoids
instance Apply (Tree n) where
(<.>) = zipWith ($)
_ .> x = x
x <. _ = x
liftF2 = zipWith
#endif
singleton :: a -> Tree 'Z a
singleton = Leaf
toList :: Tree n a -> [a]
toList t = go t [] where
go :: Tree n a -> [a] -> [a]
go (Leaf x) = (x :)
go (Node x y) = go x . go y
(!) :: Tree n a -> Wrd n -> a
(!) (Leaf x) WE = x
(!) (Node x _) (W0 is) = x ! is
(!) (Node _ y) (W1 is) = y ! is
tabulate :: forall n a. N.SNatI n => (Wrd n -> a) -> Tree n a
tabulate f = case N.snat :: N.SNat n of
N.SZ -> Leaf (f WE)
N.SS -> Node (tabulate (goLeft f)) (tabulate (goRight f))
leftmost :: Tree n a -> a
leftmost (Leaf a) = a
leftmost (Node x _) = leftmost x
rightmost :: Tree n a -> a
rightmost (Leaf a) = a
rightmost (Node _ y) = rightmost y
foldMap :: Monoid m => (a -> m) -> Tree n a -> m
foldMap f (Leaf x) = f x
foldMap f (Node x y) = mappend (foldMap f x) (foldMap f y)
ifoldMap :: Monoid m => (Wrd n -> a -> m) -> Tree n a -> m
ifoldMap f (Leaf x) = f WE x
ifoldMap f (Node x y) = mappend (ifoldMap (goLeft f) x) (ifoldMap (goRight f) y)
foldMap1 :: Semigroup s => (a -> s) -> Tree n a -> s
foldMap1 f (Leaf x) = f x
foldMap1 f (Node x y) = foldMap1 f x <> foldMap1 f y
ifoldMap1 :: Semigroup s => (Wrd n -> a -> s) -> Tree n a -> s
ifoldMap1 f (Leaf x) = f WE x
ifoldMap1 f (Node x y) = ifoldMap1 (goLeft f) x <> ifoldMap1 (goRight f) y
foldr :: (a -> b -> b) -> b -> Tree n a -> b
foldr f z (Leaf x) = f x z
foldr f z (Node x y) = foldr f (foldr f z y) x
ifoldr :: (Wrd n -> a -> b -> b) -> b -> Tree n a -> b
ifoldr f z (Leaf x) = f WE x z
ifoldr f z (Node x y) = ifoldr (goLeft f) (ifoldr (goRight f) z y) x
foldr1Map :: (a -> b -> b) -> (a -> b) -> Tree n a -> b
foldr1Map _ z (Leaf x) = z x
foldr1Map f z (Node x y) = foldr f (foldr1Map f z y) x
ifoldr1Map :: (Wrd n -> a -> b -> b) -> (Wrd n -> a -> b) -> Tree n a -> b
ifoldr1Map _ z (Leaf x) = z WE x
ifoldr1Map f z (Node x y) = ifoldr (goLeft f) (ifoldr1Map (goRight f) (goRight z) y) x
foldl :: (b -> a -> b) -> b -> Tree n a -> b
foldl f z (Leaf x) = f z x
foldl f z (Node x y) = foldl f (foldl f z x) y
ifoldl :: (Wrd n -> b -> a -> b) -> b -> Tree n a -> b
ifoldl f z (Leaf x) = f WE z x
ifoldl f z (Node x y) = ifoldl (goLeft f) (ifoldl (goRight f) z x) y
length :: Tree n a -> Int
length = go 1 where
go :: Int -> Tree n a -> Int
go !acc (Leaf _) = acc
go acc (Node x _) = go (2 * acc) x
map :: (a -> b) -> Tree n a -> Tree n b
map f (Leaf x) = Leaf (f x)
map f (Node x y) = Node (map f x) (map f y)
imap :: (Wrd n -> a -> b) -> Tree n a -> Tree n b
imap f (Leaf x) = Leaf (f WE x)
imap f (Node x y) = Node (imap (goLeft f) x) (imap (goRight f) y)
traverse :: Applicative f => (a -> f b) -> Tree n a -> f (Tree n b)
traverse f (Leaf x) = Leaf <$> f x
traverse f (Node x y) = Node <$> traverse f x <*> traverse f y
itraverse :: Applicative f => (Wrd n -> a -> f b) -> Tree n a -> f (Tree n b)
itraverse f (Leaf x) = Leaf <$> f WE x
itraverse f (Node x y) = Node <$> itraverse (goLeft f) x <*> itraverse (goRight f) y
#ifdef MIN_VERSION_semigroupoids
traverse1 :: Apply f => (a -> f b) -> Tree n a -> f (Tree n b)
traverse1 f (Leaf x) = Leaf <$> f x
traverse1 f (Node x y) = Node <$> traverse1 f x <.> traverse1 f y
itraverse1 :: Apply f => (Wrd n -> a -> f b) -> Tree n a -> f (Tree n b)
itraverse1 f (Leaf x) = Leaf <$> f WE x
itraverse1 f (Node x y) = Node <$> itraverse1 (goLeft f) x <.> itraverse1 (goRight f) y
#endif
zipWith :: (a -> b -> c) -> Tree n a -> Tree n b -> Tree n c
zipWith f (Leaf x) (Leaf y) = Leaf (f x y)
zipWith f (Node x y) (Node u v) = Node (zipWith f x u) (zipWith f y v)
izipWith :: (Wrd n -> a -> b -> c) -> Tree n a -> Tree n b -> Tree n c
izipWith f (Leaf x) (Leaf y) = Leaf (f WE x y)
izipWith f (Node x y) (Node u v) = Node (izipWith (goLeft f) x u) (izipWith (goRight f) y v)
repeat :: N.SNatI n => a -> Tree n a
repeat x = N.induction1 (Leaf x) (\t -> Node t t)
universe :: N.SNatI n => Tree n (Wrd n)
universe = tabulate id
instance N.SNatI n => QC.Arbitrary1 (Tree n) where
liftArbitrary = liftArbitrary
liftShrink = liftShrink
liftArbitrary :: forall n a. N.SNatI n => QC.Gen a -> QC.Gen (Tree n a)
liftArbitrary arb = getArb $ N.induction1 (Arb (fmap Leaf arb)) step where
step :: Arb m a -> Arb ('S m) a
step (Arb rec) = Arb $ Node <$> rec <*> rec
newtype Arb n a = Arb { getArb :: QC.Gen (Tree n a) }
liftShrink :: forall n a. (a -> [a]) -> Tree n a -> [Tree n a]
liftShrink shr (Leaf x) = Leaf <$> shr x
liftShrink shr (Node l r) = uncurry Node <$> QC.liftShrink2 rec rec (l, r) where
rec = liftShrink shr
instance (N.SNatI n, QC.Arbitrary a) => QC.Arbitrary (Tree n a) where
arbitrary = QC.arbitrary1
shrink = QC.shrink1
instance QC.CoArbitrary a => QC.CoArbitrary (Tree n a) where
coarbitrary (Leaf x) = QC.variant (0 :: Int) . QC.coarbitrary x
coarbitrary (Node l r) = QC.variant (1 :: Int) . QC.coarbitrary (l, r)
instance (N.SNatI n, QC.Function a) => QC.Function (Tree n a) where
function = case N.snat :: N.SNat n of
N.SZ -> QC.functionMap (\(Leaf x) -> x) Leaf
N.SS -> QC.functionMap (\(Node l r ) -> (l, r)) (uncurry Node)