Skip to content

Commit

Permalink
standalone deriving
Browse files Browse the repository at this point in the history
  • Loading branch information
ekmett committed Nov 3, 2011
1 parent 557a4af commit 844de69
Showing 1 changed file with 40 additions and 27 deletions.
67 changes: 40 additions & 27 deletions Data/Constraint.hs
Expand Up @@ -8,6 +8,7 @@
TypeOperators, TypeOperators,
FunctionalDependencies, FunctionalDependencies,
Rank2Types, Rank2Types,
StandaloneDeriving,
GADTs GADTs
#-} #-}


Expand Down Expand Up @@ -41,24 +42,20 @@ import Data.Complex
import Data.Ratio import Data.Ratio
import Unsafe.Coerce import Unsafe.Coerce


-- | Capture a dictionary for a given constraint
data Dict :: Constraint -> * where data Dict :: Constraint -> * where
Dict :: a => Dict a Dict :: a => Dict a


instance Eq (Dict a) where deriving instance Eq (Dict a)
Dict == Dict = True deriving instance Ord (Dict a)

deriving instance Show (Dict a)
instance Ord (Dict a) where
compare Dict Dict = EQ

instance Show (Dict a) where
showsPrec _ Dict = showString "Dict"


infixr 9 :- infixr 9 :-
-- entailment -- entailment
data (:-) :: Constraint -> Constraint -> * where data (:-) :: Constraint -> Constraint -> * where
Sub :: (a => Dict b) -> a :- b Sub :: (a => Dict b) -> a :- b


instance Eq (a :- b) where instance Eq (a :- b) where
Sub _ == Sub _ = True Sub _ == Sub _ = True


instance Ord (a :- b) where instance Ord (a :- b) where
Expand All @@ -68,41 +65,60 @@ instance Show (a :- b) where
showsPrec d (Sub _) = showParen (d > 10) $ showString "Sub Dict" showsPrec d (Sub _) = showParen (d > 10) $ showString "Sub Dict"


infixl 1 \\ -- required comment infixl 1 \\ -- required comment

-- | Given that @a :- b@, derive something that needs a context @b@, using the context @a@
(\\) :: a => (b => r) -> (a :- b) -> r (\\) :: a => (b => r) -> (a :- b) -> r
r \\ Sub Dict = r r \\ Sub Dict = r


-- due to the hack for the kind of (,) in the compiler we can't actually make (,) a bifunctor! -- | due to the hack for the kind of (,) in the current version of GHC we can't actually
-- make instances for (,) :: Constraint -> Constraint -> Constraint
(***) :: (a :- b) -> (c :- d) -> (a, c) :- (b, d) (***) :: (a :- b) -> (c :- d) -> (a, c) :- (b, d)
f *** g = Sub $ Dict \\ f \\ g f *** g = Sub $ Dict \\ f \\ g


-- weakening constraints / constraint product projections -- | Weakening a constraint product
weaken1 :: (a,b) :- a weaken1 :: (a, b) :- a
weaken1 = Sub Dict weaken1 = Sub Dict


weaken2 :: (a,b) :- b -- | Weakening a constraint product
weaken2 :: (a, b) :- b
weaken2 = Sub Dict weaken2 = Sub Dict


-- contracting constraints / diagonal morphism -- | Contracting a constraint / diagonal morphism
contract :: a :- (a, a) contract :: a :- (a, a)
contract = Sub Dict contract = Sub Dict


-- constraint product -- | Constraint product
(&&&) :: (a :- b) -> (a :- c) -> a :- (b,c) --
-- > trans weaken1 (f &&& g) = f
-- > trans weaken2 (f &&& g) = g
(&&&) :: (a :- b) -> (a :- c) -> a :- (b, c)
f &&& g = Sub $ Dict \\ f \\ g f &&& g = Sub $ Dict \\ f \\ g


-- transitivity of entailment -- ?
-- / \
-- (#) ?? ???
-- / \ / \
-- # * Constraint

-- | Transitivity of entailment
--
-- If we view '(:-)' as a Constraint-indexed category, then this is '(.)'
trans :: (b :- c) -> (a :- b) -> a :- c trans :: (b :- c) -> (a :- b) -> a :- c
trans f g = Sub $ Dict \\ f \\ g trans f g = Sub $ Dict \\ f \\ g


-- reflexivity -- | Reflexivity of entailment
--
-- If we view '(:-)' as a Constraint-indexed category, then this is 'id'
refl :: a :- a refl :: a :- a
refl = Sub Dict refl = Sub Dict


-- terminal arrows -- | Every constraint implies truth
--
-- These are the terminal arrows of the category, and () is the terminal object.
top :: a :- () top :: a :- ()
top = Sub Dict top = Sub Dict


-- don't do this! -- | Don't be evil
evil :: a :- b evil :: a :- b
evil = unsafeCoerce refl evil = unsafeCoerce refl


Expand All @@ -116,10 +132,10 @@ class (b :: Constraint) :=> (h :: Constraint) | h -> b where
instance Class () (Class b a) where cls = Sub Dict instance Class () (Class b a) where cls = Sub Dict
instance Class () (b :=> a) where cls = Sub Dict instance Class () (b :=> a) where cls = Sub Dict


-- bootstrapping

#ifdef UNDECIDABLE #ifdef UNDECIDABLE
-- | Decidable under GHC HEAD
instance Class b a => () :=> Class b a where ins = Sub Dict instance Class b a => () :=> Class b a where ins = Sub Dict
-- | Decidable under GHC HEAD
instance (b :=> a) => () :=> b :=> a where ins = Sub Dict instance (b :=> a) => () :=> b :=> a where ins = Sub Dict
#endif #endif


Expand Down Expand Up @@ -299,9 +315,7 @@ instance a => Bounded (Dict a) where
maxBound = Dict maxBound = Dict


instance a :=> Read (Dict a) where ins = Sub Dict instance a :=> Read (Dict a) where ins = Sub Dict
instance a => Read (Dict a) where deriving instance a => Read (Dict a)
readsPrec d = readParen (d > 10) $ \s ->
[ (Dict, t) | ("Dict", t) <- lex s ]


instance a :=> Monoid (Dict a) where ins = Sub Dict instance a :=> Monoid (Dict a) where ins = Sub Dict
instance a => Monoid (Dict a) where instance a => Monoid (Dict a) where
Expand All @@ -315,7 +329,6 @@ applicative m = m \\ trans (evil :: Applicative (WrappedMonad m) :- Applicative
alternative :: forall m a. MonadPlus m => (Alternative m => m a) -> m a alternative :: forall m a. MonadPlus m => (Alternative m => m a) -> m a
alternative m = m \\ trans (evil :: Alternative (WrappedMonad m) :- Alternative m) ins alternative m = m \\ trans (evil :: Alternative (WrappedMonad m) :- Alternative m) ins


-- Using applicative sugar given just a monad, no lifting needed -- Demonstration of the use of applicative sugar given just a monad, no lifting needed
(<&>) :: Monad m => m a -> m b -> m (a, b) (<&>) :: Monad m => m a -> m b -> m (a, b)
m <&> n = applicative $ (,) <$> m <*> n m <&> n = applicative $ (,) <$> m <*> n

0 comments on commit 844de69

Please sign in to comment.