{-# LANGUAGE TemplateHaskell, ViewPatterns, PolyKinds, GADTs, PatternGuards #-}
module Data.Binding.Hobbits.Closed (
Closed(),
unClosed, mkClosed, noClosedNames, clApply, clMbApply, clApplyCl, unsafeClose,
Closable(..)
) where
import Data.Proxy
import Data.Type.RList
import Data.Binding.Hobbits.Internal.Name
import Data.Binding.Hobbits.Internal.Mb
import Data.Binding.Hobbits.Internal.Closed
import Data.Binding.Hobbits.Mb
noClosedNames :: Closed (Name a) -> b
noClosedNames (Closed n) =
case cmpName n n of
_ ->
error $
"... Clever girl!" ++
"The `noClosedNames' invariant has somehow been violated."
clApply :: Closed (a -> b) -> Closed a -> Closed b
clApply (Closed f) (Closed a) = Closed (f a)
clMbApply :: Closed (Mb ctx (a -> b)) -> Closed (Mb ctx a) ->
Closed (Mb ctx b)
clMbApply (Closed f) (Closed a) = Closed (mbApply f a)
clApplyCl :: Closed (Closed a -> b) -> Closed a -> Closed b
clApplyCl (Closed f) a = Closed (f a)
closeBug :: a -> Closed a
closeBug = $([| \x -> $(mkClosed [| x |]) |])
unsafeClose :: a -> Closed a
unsafeClose = Closed
class Closable a where
toClosed :: a -> Closed a
instance Closable Integer where
toClosed i = Closed i
instance Closable (Member ctx a) where
toClosed memb = Closed memb
instance Closable (Proxy a) where
toClosed Proxy = $(mkClosed [| Proxy |])
instance Closable (Closed a) where
toClosed = clApplyCl $(mkClosed [| id |])
instance Closable Bool where
toClosed True = $(mkClosed [| True |])
toClosed False = $(mkClosed [| False |])
instance Closable Char where
toClosed = unsafeClose
instance Closable Int where
toClosed = unsafeClose
instance Closable a => Closable [a] where
toClosed [] = $(mkClosed [| [] |])
toClosed (a:as) =
$(mkClosed [| (:) |]) `clApply` toClosed a `clApply` toClosed as
data IsClosable a where IsClosable :: Closable a => IsClosable a
class ClosableAny1 f where
closableAny1 :: f a -> IsClosable (f a)
toClosedAny1 :: ClosableAny1 f => f a -> Closed (f a)
toClosedAny1 x | IsClosable <- closableAny1 x = toClosed x
instance ClosableAny1 Proxy where
closableAny1 _ = IsClosable
instance ClosableAny1 (Member ctx) where
closableAny1 _ = IsClosable
instance ClosableAny1 f => Closable (RAssign f ctx) where
toClosed MNil = $(mkClosed [| MNil |])
toClosed (xs :>: x) =
$(mkClosed [| (:>:) |]) `clApply` toClosed xs `clApply` toClosedAny1 x