{-# LANGUAGE GADTs, TypeFamilies, TypeOperators, CPP, FlexibleContexts, FlexibleInstances, MultiParamTypeClasses #-}
----------------------------------------------------------------------
-- |
-- Module : Data.Semigroupoid.Trie
-- Copyright : (c) Edward Kmett 2011
-- License : BSD3
--
-- Maintainer : ekmett@gmail.com
-- Stability : experimental
--
-- We may not be able to build a category out of tries, but we can
-- consruct a semigroupoid.
----------------------------------------------------------------------
module Data.Semigroupoid.Trie
( (:->:)(..)
, Entry(..)
, runT
) where
import Control.Applicative
import Control.Arrow (first,(&&&))
import Control.Comonad
import Control.Monad.Representable
import Control.Monad.Reader
import Control.Monad.Reader.Trie
import Data.Bits
import Data.Distributive
import Data.Function (on)
import Data.Functor.Adjunction
import Data.Functor.Bind
import Data.Foldable
import Data.Int
import Data.Key
import Data.Monoid
import Data.Traversable
import Data.Semigroup
import Data.Semigroup.Traversable
import Data.Semigroup.Foldable
import Data.Semigroupoid
-- import Data.Semigroupoid.Ob
import Data.Word
data a :->: b where
T :: HasTrie a => Trie a b -> a :->: b
type instance Key ((:->:) a) = a
data Entry a b = Entry a b
instance Functor (Entry a) where
fmap f (Entry a b) = Entry a (f b)
runT :: (a :->: b) -> Trie a b
runT (T f) = f
instance Index ((:->:)e) where
index (T f) = untrie f
instance HasTrie e => Distributive ((:->:)e) where
distribute = distributeRep
instance HasTrie e => Representable ((:->:) e) where
tabulate f = T (trie f)
instance HasTrie e => Adjunction (Entry e) ((:->:) e) where
unit = mapWithKey Entry . pure
counit (Entry a t) = index t a
instance Functor ((:->:) a) where
fmap f (T g) = T (fmap f g)
instance Keyed ((:->:) a) where
mapWithKey f (T a) = T (mapWithKey (f . uncoerceKey) a)
instance Foldable ((:->:) a) where
foldMap f (T a) = foldMap f a
instance FoldableWithKey ((:->:) a) where
foldMapWithKey f (T a) = foldMapWithKey (f . uncoerceKey) a
instance Traversable ((:->:) a) where
traverse f (T a) = T <$> traverse f a
instance TraversableWithKey ((:->:) a) where
traverseWithKey f (T a) = T <$> traverseWithKey (f . uncoerceKey) a
instance Foldable1 ((:->:) a) where
foldMap1 f (T a) = foldMap1 f a
instance FoldableWithKey1 ((:->:) a) where
foldMapWithKey1 f (T a) = foldMapWithKey1 (f . uncoerceKey) a
instance Traversable1 ((:->:) a) where
traverse1 f (T a) = T <$> traverse1 f a
instance TraversableWithKey1 ((:->:) a) where
traverseWithKey1 f (T a) = T <$> traverseWithKey1 (f . uncoerceKey) a
instance Eq b => Eq (a :->: b) where
(==) = (==) `on` toList
instance Ord b => Ord (a :->: b) where
compare = compare `on` toList
instance (Show a, Show b) => Show (a :->: b) where
showsPrec d t = showsPrec d (toIndexedList t)
instance Apply ((:->:) a) where
T f <.> T g = T (f <.> g)
a <. _ = a
_ .> b = b
instance Semigroupoid (:->:) where
o (T f) = fmap (index f . coerceKey)
-- instance HasTrie a => Ob (:->:) a where semiid = T return
instance HasTrie a => Applicative ((:->:) a) where
pure a = T (pure a)
T f <*> T g = T (f <*> g)
a <* _ = a
_ *> b = b
instance Bind ((:->:) a) where
T m >>- f = T (tabulate (\a -> index (runT (f (index m a))) a))
instance HasTrie a => Monad ((:->:) a) where
return a = T (return a)
(>>=) = (>>-)
_ >> m = m
instance HasTrie a => MonadReader a ((:->:) a) where
ask = askRep
local = localRep
instance (HasTrie m, Semigroup m, Monoid m) => Comonad ((:->:) m) where
extract = flip index mempty
-- TODO: remove dependency on HasTrie
instance (HasTrie m, Semigroup m) => Extend ((:->:) m) where
duplicate = duplicateRep