enumerate-0.0.0: sources/Data/Enumerate/Domain.hs
{-# LANGUAGE DeriveGeneric, DefaultSignatures, TypeOperators, FlexibleInstances, FlexibleContexts, DeriveAnyClass, TypeFamilies, LambdaCase, EmptyCase, MultiParamTypeClasses #-}
{- |
e.g. generate a boilerplate 'HasTrie' instance for a @Context@ type that has both sum types and product types
@
data Context
= GlobalContext | EmacsContext BufferName BufferMode BufferContents | OtherContext String
deriving (Show,Generic)
-- Strings are infinite, so Context is too, that's okay
instance HasDomain Context
type BufferName = String
type BufferMode = String
type BufferContents = String
instance HasTrie Context where
type a :->: b = ContextTrie ('TrieGeneric' a b)
trie = 'trieGeneric'
untrie = 'untrieGeneric'
@
the conversions (between a type @a@ and its representation @(Rep a x)@) make the generic instance
slower than a manual instance.
but, if the function you're memoizing is costly enough, and the datatype it consumes is messy enough,
the four-line @HasTrie@ instance (and a one line call to 'memo') can save both runtime and developer time.
-}
module Data.Enumerate.Domain where
import Data.CoRec
import Data.MemoTrie
import GHC.Generics
-- class GHasTrie f a where
-- type GTrie f a :: (* -> *)
-- -- type GTrie f :: (* -> *) -> * -> * -> (* -> *)
-- gtrie :: f p -> (a -> ) -> (GTrie f a) p
-- guntrie :: (GTrie f a) p -> (a -> )
-- -- | zero cases become (one case with) zero fields
-- instance GHasTrie (V1) a where
-- type GTrie (V1) a = (U1)
-- gtrie _ = (U1)
-- -- | one case becomes (one case with) one field
-- instance GHasTrie (U1) a where
-- type GTrie (U1) a = (K1 () a)
-- -- gtrie (U1) = (K1 a)
-- gtrie (U1) = undefined
-- -- | call 'trie'
-- instance (HasTrie a) => GHasTrie (K1 i a) where
-- type GTrie (K1 i a) = Trie a
-- gtrie (K1 a) = trie a
-- -- -- | two cases become (one case with) two fields
-- -- instance (GHasTrie (f), GHasTrie (g)) => GHasTrie (f :+: g) where
-- -- type GTrie (f :+: g) = Either (GTrie f) (GTrie g)
-- -- gtrie (L1 f) = Left (gtrie f)
-- -- gtrie (R1 g) = Right (gtrie g)
-- -- -- | two fields become (one case with) (one field of) two arrows
-- -- instance (GHasDomain (f), GHasDomain (g)) => GHasDomain (f :*: g) where
-- -- type GDomain (f :*: g) = ((GDomain f), (GDomain g))
-- -- gdomain (f :*: g) = (gdomain f, gdomain g)
-- -- -- | (ignore metadata)
-- -- instance (GHasDomain (f)) => GHasDomain (M1 i a f) where
-- -- type GDomain (M1 i a f) = (GDomain f)
-- -- gdomain (M1 f) = gdomain f
-- {- |
-- e.g.
-- @
-- a ~ Context
-- Rep a ~
-- GDomain (Rep a) ~
-- GCanonical (GDomain (Rep a)) ~
-- @
-- -}
-- -- type TrieGeneric a = GCanonical (GDomain (Rep a))
-- -- trieGeneric ::
-- -- trieGeneric =
-- -- untrieGeneric ::
-- -- untrieGeneric =