|
@ -7,8 +7,10 @@ import Control.Monad.Reader |
|
|
import Control.Exception |
|
|
import Control.Exception |
|
|
|
|
|
|
|
|
import qualified Data.Map.Strict as Map |
|
|
import qualified Data.Map.Strict as Map |
|
|
|
|
|
import qualified Data.Sequence as Seq |
|
|
import qualified Data.Set as Set |
|
|
import qualified Data.Set as Set |
|
|
import qualified Data.Text as T |
|
|
import qualified Data.Text as T |
|
|
|
|
|
import Data.Sequence (Seq) |
|
|
import Data.Traversable |
|
|
import Data.Traversable |
|
|
import Data.Set (Set) |
|
|
import Data.Set (Set) |
|
|
import Data.Typeable |
|
|
import Data.Typeable |
|
@ -16,31 +18,34 @@ import Data.Foldable |
|
|
import Data.IORef |
|
|
import Data.IORef |
|
|
import Data.Maybe |
|
|
import Data.Maybe |
|
|
|
|
|
|
|
|
import {-# SOURCE #-} Elab.WiredIn |
|
|
|
|
|
import Elab.Monad |
|
|
import Elab.Monad |
|
|
|
|
|
|
|
|
import Presyntax.Presyntax (Plicity(..)) |
|
|
import Presyntax.Presyntax (Plicity(..)) |
|
|
|
|
|
|
|
|
|
|
|
import Syntax.Pretty |
|
|
import Syntax |
|
|
import Syntax |
|
|
|
|
|
|
|
|
import System.IO.Unsafe |
|
|
import System.IO.Unsafe |
|
|
import Syntax.Pretty |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import {-# SOURCE #-} Elab.WiredIn |
|
|
|
|
|
import Prettyprinter |
|
|
|
|
|
|
|
|
eval :: Term -> ElabM Value |
|
|
eval :: Term -> ElabM Value |
|
|
eval t = asks (flip evalWithEnv t) |
|
|
|
|
|
|
|
|
eval t = asks (flip eval' t) |
|
|
|
|
|
|
|
|
forceIO :: MonadIO m => Value -> m Value |
|
|
forceIO :: MonadIO m => Value -> m Value |
|
|
forceIO vl@(VNe (HMeta (MV _ cell)) args) = do |
|
|
forceIO vl@(VNe (HMeta (MV _ cell)) args) = do |
|
|
solved <- liftIO $ readIORef cell |
|
|
solved <- liftIO $ readIORef cell |
|
|
case solved of |
|
|
case solved of |
|
|
Just vl -> forceIO $ foldl applProj vl (reverse args) |
|
|
|
|
|
|
|
|
Just vl -> forceIO $ foldl applProj vl args |
|
|
Nothing -> pure vl |
|
|
Nothing -> pure vl |
|
|
forceIO x = pure x |
|
|
forceIO x = pure x |
|
|
|
|
|
|
|
|
applProj :: Value -> Projection -> Value |
|
|
applProj :: Value -> Projection -> Value |
|
|
applProj fun (PApp p arg) = vApp p fun arg |
|
|
|
|
|
applProj fun PProj1 = vProj1 fun |
|
|
|
|
|
applProj fun PProj2 = vProj2 fun |
|
|
|
|
|
|
|
|
applProj fun (PApp p arg) = vApp p fun arg |
|
|
|
|
|
applProj fun (PIElim l x y i) = ielim l x y fun i |
|
|
|
|
|
applProj fun PProj1 = vProj1 fun |
|
|
|
|
|
applProj fun PProj2 = vProj2 fun |
|
|
|
|
|
|
|
|
force :: Value -> Value |
|
|
force :: Value -> Value |
|
|
force = unsafePerformIO . forceIO |
|
|
force = unsafePerformIO . forceIO |
|
@ -53,11 +58,12 @@ zonkIO (VNe hd sp) = do |
|
|
HMeta (MV _ cell) -> do |
|
|
HMeta (MV _ cell) -> do |
|
|
solved <- liftIO $ readIORef cell |
|
|
solved <- liftIO $ readIORef cell |
|
|
case solved of |
|
|
case solved of |
|
|
Just vl -> zonkIO $ foldl applProj vl (reverse sp') |
|
|
|
|
|
|
|
|
Just vl -> zonkIO $ foldl applProj vl sp' |
|
|
Nothing -> pure $ VNe hd sp' |
|
|
Nothing -> pure $ VNe hd sp' |
|
|
hd -> pure $ VNe hd sp' |
|
|
hd -> pure $ VNe hd sp' |
|
|
where |
|
|
where |
|
|
zonkSp (PApp p x) = PApp p <$> zonkIO x |
|
|
zonkSp (PApp p x) = PApp p <$> zonkIO x |
|
|
|
|
|
zonkSp (PIElim l x y i) = PIElim <$> zonkIO l <*> zonkIO x <*> zonkIO y <*> zonkIO i |
|
|
zonkSp PProj1 = pure PProj1 |
|
|
zonkSp PProj1 = pure PProj1 |
|
|
zonkSp PProj2 = pure PProj2 |
|
|
zonkSp PProj2 = pure PProj2 |
|
|
zonkIO (VLam p (Closure s k)) = pure $ VLam p (Closure s (zonk . k)) |
|
|
zonkIO (VLam p (Closure s k)) = pure $ VLam p (Closure s (zonk . k)) |
|
@ -65,6 +71,9 @@ zonkIO (VPi p d (Closure s k)) = VPi p <$> zonkIO d <*> pure (Closure s (zonk . |
|
|
zonkIO (VSigma d (Closure s k)) = VSigma <$> zonkIO d <*> pure (Closure s (zonk . k)) |
|
|
zonkIO (VSigma d (Closure s k)) = VSigma <$> zonkIO d <*> pure (Closure s (zonk . k)) |
|
|
zonkIO (VPair a b) = VPair <$> zonkIO a <*> zonkIO b |
|
|
zonkIO (VPair a b) = VPair <$> zonkIO a <*> zonkIO b |
|
|
|
|
|
|
|
|
|
|
|
zonkIO (VPath line x y) = VPath <$> zonkIO line <*> zonkIO x <*> zonkIO y |
|
|
|
|
|
zonkIO (VLine line f) = VLine <$> zonkIO line <*> zonkIO f |
|
|
|
|
|
|
|
|
-- Sorts |
|
|
-- Sorts |
|
|
zonkIO VType = pure VType |
|
|
zonkIO VType = pure VType |
|
|
zonkIO VTypeω = pure VTypeω |
|
|
zonkIO VTypeω = pure VTypeω |
|
@ -80,55 +89,65 @@ zonkIO (VINot x) = inot <$> zonkIO x |
|
|
zonk :: Value -> Value |
|
|
zonk :: Value -> Value |
|
|
zonk = unsafePerformIO . zonkIO |
|
|
zonk = unsafePerformIO . zonkIO |
|
|
|
|
|
|
|
|
evalWithEnv :: ElabEnv -> Term -> Value |
|
|
|
|
|
evalWithEnv env (Ref x) = |
|
|
|
|
|
|
|
|
eval' :: ElabEnv -> Term -> Value |
|
|
|
|
|
eval' env (Ref x) = |
|
|
case Map.lookup x (getEnv env) of |
|
|
case Map.lookup x (getEnv env) of |
|
|
Just (_, vl) -> vl |
|
|
Just (_, vl) -> vl |
|
|
_ -> error "variable not in scope when evaluating" |
|
|
_ -> error "variable not in scope when evaluating" |
|
|
evalWithEnv env (App p f x) = vApp p (evalWithEnv env f) (evalWithEnv env x) |
|
|
|
|
|
|
|
|
eval' env (App p f x) = vApp p (eval' env f) (eval' env x) |
|
|
|
|
|
|
|
|
evalWithEnv env (Lam p s t) = |
|
|
|
|
|
|
|
|
eval' env (Lam p s t) = |
|
|
VLam p $ Closure s $ \a -> |
|
|
VLam p $ Closure s $ \a -> |
|
|
evalWithEnv env { getEnv = Map.insert (Bound s) (error "type of abs", a) (getEnv env) } t |
|
|
|
|
|
|
|
|
eval' env { getEnv = Map.insert (Bound s) (error "type of abs", a) (getEnv env) } t |
|
|
|
|
|
|
|
|
|
|
|
eval' env (Pi p s d t) = |
|
|
|
|
|
VPi p (eval' env d) $ Closure s $ \a -> |
|
|
|
|
|
eval' env { getEnv = (Map.insert (Bound s) (error "type of abs", a) (getEnv env))} t |
|
|
|
|
|
|
|
|
evalWithEnv env (Pi p s d t) = |
|
|
|
|
|
VPi p (evalWithEnv env d) $ Closure s $ \a -> |
|
|
|
|
|
evalWithEnv env { getEnv = (Map.insert (Bound s) (error "type of abs", a) (getEnv env))} t |
|
|
|
|
|
|
|
|
eval' _ (Meta m) = VNe (HMeta m) mempty |
|
|
|
|
|
|
|
|
evalWithEnv _ (Meta m) = VNe (HMeta m) [] |
|
|
|
|
|
|
|
|
eval' env (Sigma s d t) = |
|
|
|
|
|
VSigma (eval' env d) $ Closure s $ \a -> |
|
|
|
|
|
eval' env { getEnv = Map.insert (Bound s) (error "type of abs", a) (getEnv env) } t |
|
|
|
|
|
|
|
|
evalWithEnv env (Sigma s d t) = |
|
|
|
|
|
VSigma (evalWithEnv env d) $ Closure s $ \a -> |
|
|
|
|
|
evalWithEnv env { getEnv = Map.insert (Bound s) (error "type of abs", a) (getEnv env) } t |
|
|
|
|
|
|
|
|
eval' e (Pair a b) = VPair (eval' e a) (eval' e b) |
|
|
|
|
|
|
|
|
evalWithEnv e (Pair a b) = VPair (evalWithEnv e a) (evalWithEnv e b) |
|
|
|
|
|
|
|
|
eval' e (Proj1 a) = vProj1 (eval' e a) |
|
|
|
|
|
eval' e (Proj2 a) = vProj2 (eval' e a) |
|
|
|
|
|
|
|
|
evalWithEnv e (Proj1 a) = vProj1 (evalWithEnv e a) |
|
|
|
|
|
evalWithEnv e (Proj2 a) = vProj2 (evalWithEnv e a) |
|
|
|
|
|
|
|
|
eval' _ Type = VType |
|
|
|
|
|
eval' _ Typeω = VTypeω |
|
|
|
|
|
eval' _ I = VI |
|
|
|
|
|
eval' _ I0 = VI0 |
|
|
|
|
|
eval' _ I1 = VI1 |
|
|
|
|
|
|
|
|
evalWithEnv _ Type = VType |
|
|
|
|
|
evalWithEnv _ Typeω = VTypeω |
|
|
|
|
|
evalWithEnv _ I = VI |
|
|
|
|
|
evalWithEnv _ I0 = VI0 |
|
|
|
|
|
evalWithEnv _ I1 = VI1 |
|
|
|
|
|
|
|
|
eval' e (IAnd x y) = iand (eval' e x) (eval' e y) |
|
|
|
|
|
eval' e (IOr x y) = ior (eval' e x) (eval' e y) |
|
|
|
|
|
eval' e (INot x) = inot (eval' e x) |
|
|
|
|
|
|
|
|
evalWithEnv e (IAnd x y) = iand (evalWithEnv e x) (evalWithEnv e y) |
|
|
|
|
|
evalWithEnv e (IOr x y) = ior (evalWithEnv e x) (evalWithEnv e y) |
|
|
|
|
|
evalWithEnv e (INot x) = inot (evalWithEnv e x) |
|
|
|
|
|
|
|
|
eval' e (PathP l a b) = VPath (eval' e l) (eval' e a) (eval' e b) |
|
|
|
|
|
eval' e (IElim l x y f i) = ielim (eval' e l) (eval' e x) (eval' e y) (eval' e f) (eval' e i) |
|
|
|
|
|
eval' e (PathIntro p f) = VLine (eval' e p) (eval' e f) |
|
|
|
|
|
|
|
|
vApp :: Plicity -> Value -> Value -> Value |
|
|
vApp :: Plicity -> Value -> Value -> Value |
|
|
vApp p (VLam p' k) arg = assert (p == p') $ clCont k arg |
|
|
|
|
|
vApp p (VNe h sp) arg = VNe h (PApp p arg:sp) |
|
|
|
|
|
|
|
|
vApp p (VLam p' k) arg |
|
|
|
|
|
| p == p' = clCont k arg |
|
|
|
|
|
| otherwise = error $ "wrong plicity " ++ show p ++ " vs " ++ show p' ++ " in app " ++ show (App p (quote (VLam p' k)) (quote arg)) |
|
|
|
|
|
vApp p (VNe h sp) arg = VNe h (sp Seq.:|> PApp p arg) |
|
|
vApp _ x _ = error $ "can't apply " ++ show x |
|
|
vApp _ x _ = error $ "can't apply " ++ show x |
|
|
|
|
|
|
|
|
|
|
|
(@@) :: Value -> Value -> Value |
|
|
|
|
|
(@@) = vApp Ex |
|
|
|
|
|
infixl 9 @@ |
|
|
|
|
|
|
|
|
vProj1 :: Value -> Value |
|
|
vProj1 :: Value -> Value |
|
|
vProj1 (VPair a _) = a |
|
|
vProj1 (VPair a _) = a |
|
|
vProj1 (VNe h sp) = VNe h (PProj1:sp) |
|
|
|
|
|
|
|
|
vProj1 (VNe h sp) = VNe h (sp Seq.:|> PProj1) |
|
|
vProj1 x = error $ "can't proj1 " ++ show x |
|
|
vProj1 x = error $ "can't proj1 " ++ show x |
|
|
|
|
|
|
|
|
vProj2 :: Value -> Value |
|
|
vProj2 :: Value -> Value |
|
|
vProj2 (VPair _ b) = b |
|
|
vProj2 (VPair _ b) = b |
|
|
vProj2 (VNe h sp) = VNe h (PProj2:sp) |
|
|
|
|
|
|
|
|
vProj2 (VNe h sp) = VNe h (sp Seq.:|> PProj2) |
|
|
vProj2 x = error $ "can't proj2 " ++ show x |
|
|
vProj2 x = error $ "can't proj2 " ++ show x |
|
|
|
|
|
|
|
|
data NotEqual = NotEqual Value Value |
|
|
data NotEqual = NotEqual Value Value |
|
@ -141,8 +160,13 @@ unify' topa topb = join $ go <$> forceIO topa <*> forceIO topb where |
|
|
|
|
|
|
|
|
go (VNe x a) (VNe x' a') |
|
|
go (VNe x a) (VNe x' a') |
|
|
| x == x', length a == length a' = |
|
|
| x == x', length a == length a' = |
|
|
traverse_ (uncurry unify'Spine) (zip a a') |
|
|
|
|
|
| otherwise = fail |
|
|
|
|
|
|
|
|
traverse_ (uncurry unify'Spine) (Seq.zip a a') |
|
|
|
|
|
|
|
|
|
|
|
go (VNe _hd (_ Seq.:|> PIElim _l x y i)) rhs = |
|
|
|
|
|
case force i of |
|
|
|
|
|
VI0 -> unify' x rhs |
|
|
|
|
|
VI1 -> unify' y rhs |
|
|
|
|
|
_ -> fail |
|
|
|
|
|
|
|
|
go (VLam p (Closure _ k)) vl = do |
|
|
go (VLam p (Closure _ k)) vl = do |
|
|
t <- VVar . Bound <$> newName |
|
|
t <- VVar . Bound <$> newName |
|
@ -171,6 +195,23 @@ unify' topa topb = join $ go <$> forceIO topa <*> forceIO topb where |
|
|
go VI VI = pure () |
|
|
go VI VI = pure () |
|
|
go VI0 VI0 = pure () |
|
|
go VI0 VI0 = pure () |
|
|
go VI1 VI1 = pure () |
|
|
go VI1 VI1 = pure () |
|
|
|
|
|
|
|
|
|
|
|
go (VINot x) (VINot y) = unify' x y |
|
|
|
|
|
go (VIAnd x y) (VIAnd x' y') = unify' x x' *> unify' y y' |
|
|
|
|
|
go (VIOr x y) (VIOr x' y') = unify' x x' *> unify' y y' |
|
|
|
|
|
|
|
|
|
|
|
go (VPath l x y) (VPath l' x' y') = do |
|
|
|
|
|
unify' l l' |
|
|
|
|
|
unify' x x' |
|
|
|
|
|
unify' y y' |
|
|
|
|
|
|
|
|
|
|
|
go (VLine l p) p' = do |
|
|
|
|
|
n <- VVar . Bound <$> newName |
|
|
|
|
|
unify (p @@ n) (ielim l (l @@ VI0) (l @@ VI1) p' n) |
|
|
|
|
|
|
|
|
|
|
|
go p' (VLine l p) = do |
|
|
|
|
|
n <- VVar . Bound <$> newName |
|
|
|
|
|
unify (ielim l (l @@ VI0) (l @@ VI1) p' n) (p @@ n) |
|
|
|
|
|
|
|
|
go _ _ = fail |
|
|
go _ _ = fail |
|
|
|
|
|
|
|
@ -182,6 +223,8 @@ unify' topa topb = join $ go <$> forceIO topa <*> forceIO topb where |
|
|
unify'Spine PProj1 PProj1 = pure () |
|
|
unify'Spine PProj1 PProj1 = pure () |
|
|
unify'Spine PProj2 PProj2 = pure () |
|
|
unify'Spine PProj2 PProj2 = pure () |
|
|
|
|
|
|
|
|
|
|
|
unify'Spine (PIElim _ _ _ i) (PIElim _ _ _ j) = unify' i j |
|
|
|
|
|
|
|
|
unify'Spine _ _ = fail |
|
|
unify'Spine _ _ = fail |
|
|
|
|
|
|
|
|
unify :: Value -> Value -> ElabM () |
|
|
unify :: Value -> Value -> ElabM () |
|
@ -191,8 +234,17 @@ isConvertibleTo :: Value -> Value -> ElabM (Term -> Term) |
|
|
VPi Im d (Closure _v k) `isConvertibleTo` ty = do |
|
|
VPi Im d (Closure _v k) `isConvertibleTo` ty = do |
|
|
meta <- newMeta d |
|
|
meta <- newMeta d |
|
|
cont <- k meta `isConvertibleTo` ty |
|
|
cont <- k meta `isConvertibleTo` ty |
|
|
pure (\f -> cont (App Ex f (quote meta))) |
|
|
|
|
|
|
|
|
pure (\f -> cont (App Im f (quote meta))) |
|
|
VType `isConvertibleTo` VTypeω = pure id |
|
|
VType `isConvertibleTo` VTypeω = pure id |
|
|
|
|
|
|
|
|
|
|
|
VPi p d (Closure _ k) `isConvertibleTo` VPi p' d' (Closure _ k') | p == p' = do |
|
|
|
|
|
wp <- d' `isConvertibleTo` d |
|
|
|
|
|
n <- newName |
|
|
|
|
|
wp_n <- eval (Lam Ex n (wp (Ref (Bound n)))) |
|
|
|
|
|
|
|
|
|
|
|
wp' <- k (VVar (Bound n)) `isConvertibleTo` k' (wp_n @@ VVar (Bound n)) |
|
|
|
|
|
pure (\f -> Lam p n (wp' (App p f (wp (Ref (Bound n)))))) |
|
|
|
|
|
|
|
|
isConvertibleTo a b = do |
|
|
isConvertibleTo a b = do |
|
|
unify' a b |
|
|
unify' a b |
|
|
pure id |
|
|
pure id |
|
@ -210,7 +262,7 @@ newMeta _dom = do |
|
|
Bound{} -> Just (PApp Ex (VVar n)) |
|
|
Bound{} -> Just (PApp Ex (VVar n)) |
|
|
_ -> Nothing |
|
|
_ -> Nothing |
|
|
|
|
|
|
|
|
pure (VNe (HMeta m) (catMaybes t)) |
|
|
|
|
|
|
|
|
pure (VNe (HMeta m) (Seq.fromList (catMaybes t))) |
|
|
|
|
|
|
|
|
newName :: MonadIO m => m T.Text |
|
|
newName :: MonadIO m => m T.Text |
|
|
newName = liftIO $ do |
|
|
newName = liftIO $ do |
|
@ -221,14 +273,14 @@ _nameCounter :: IORef Int |
|
|
_nameCounter = unsafePerformIO $ newIORef 0 |
|
|
_nameCounter = unsafePerformIO $ newIORef 0 |
|
|
{-# NOINLINE _nameCounter #-} |
|
|
{-# NOINLINE _nameCounter #-} |
|
|
|
|
|
|
|
|
solveMeta :: MV -> [Projection] -> Value -> ElabM () |
|
|
|
|
|
|
|
|
solveMeta :: MV -> Seq Projection -> Value -> ElabM () |
|
|
solveMeta m@(MV _ cell) sp rhs = do |
|
|
solveMeta m@(MV _ cell) sp rhs = do |
|
|
env <- ask |
|
|
env <- ask |
|
|
liftIO $ putStrLn (showValue (VNe (HMeta m) sp) ++ " ≡? " ++ showValue rhs) |
|
|
|
|
|
names <- checkSpine Set.empty sp |
|
|
names <- checkSpine Set.empty sp |
|
|
checkScope (Set.fromList (Bound <$> names)) rhs |
|
|
checkScope (Set.fromList (Bound <$> names)) rhs |
|
|
|
|
|
`withNote` hsep [prettyTm (quote (VNe (HMeta m) sp)), pretty '≡', prettyTm (quote rhs)] |
|
|
let tm = quote rhs |
|
|
let tm = quote rhs |
|
|
lam = evalWithEnv env $ foldr (Lam Ex) tm names |
|
|
|
|
|
|
|
|
lam = eval' env $ foldr (Lam Ex) tm names |
|
|
liftIO . atomicModifyIORef' cell $ \case |
|
|
liftIO . atomicModifyIORef' cell $ \case |
|
|
Just _ -> error "filled cell in solvedMeta" |
|
|
Just _ -> error "filled cell in solvedMeta" |
|
|
Nothing -> (Just lam, ()) |
|
|
Nothing -> (Just lam, ()) |
|
@ -245,6 +297,7 @@ checkScope scope (VNe h sp) = |
|
|
traverse_ checkProj sp |
|
|
traverse_ checkProj sp |
|
|
where |
|
|
where |
|
|
checkProj (PApp _ t) = checkScope scope t |
|
|
checkProj (PApp _ t) = checkScope scope t |
|
|
|
|
|
checkProj (PIElim l x y i) = traverse_ (checkScope scope) [l, x, y, i] |
|
|
checkProj PProj1 = pure () |
|
|
checkProj PProj1 = pure () |
|
|
checkProj PProj2 = pure () |
|
|
checkProj PProj2 = pure () |
|
|
|
|
|
|
|
@ -272,12 +325,15 @@ checkScope s (VIAnd x y) = traverse_ (checkScope s) [x, y] |
|
|
checkScope s (VIOr x y) = traverse_ (checkScope s) [x, y] |
|
|
checkScope s (VIOr x y) = traverse_ (checkScope s) [x, y] |
|
|
checkScope s (VINot x) = checkScope s x |
|
|
checkScope s (VINot x) = checkScope s x |
|
|
|
|
|
|
|
|
checkSpine :: Set Name -> [Projection] -> ElabM [T.Text] |
|
|
|
|
|
checkSpine scope (PApp Ex (VVar n@(Bound t)):xs) |
|
|
|
|
|
|
|
|
checkScope s (VPath line a b) = traverse_ (checkScope s) [line, a, b] |
|
|
|
|
|
checkScope s (VLine _ line) = checkScope s line |
|
|
|
|
|
|
|
|
|
|
|
checkSpine :: Set Name -> Seq Projection -> ElabM [T.Text] |
|
|
|
|
|
checkSpine scope (PApp Ex (VVar n@(Bound t)) Seq.:<| xs) |
|
|
| n `Set.member` scope = liftIO . throwIO $ NonLinearSpine n |
|
|
| n `Set.member` scope = liftIO . throwIO $ NonLinearSpine n |
|
|
| otherwise = (t:) <$> checkSpine scope xs |
|
|
| otherwise = (t:) <$> checkSpine scope xs |
|
|
checkSpine _ (p:_) = liftIO . throwIO $ SpineProj p |
|
|
|
|
|
checkSpine _ [] = pure [] |
|
|
|
|
|
|
|
|
checkSpine _ (p Seq.:<| _) = liftIO . throwIO $ SpineProj p |
|
|
|
|
|
checkSpine _ Seq.Empty = pure [] |
|
|
|
|
|
|
|
|
newtype NonLinearSpine = NonLinearSpine { getDupeName :: Name } |
|
|
newtype NonLinearSpine = NonLinearSpine { getDupeName :: Name } |
|
|
deriving (Show, Typeable, Exception) |
|
|
deriving (Show, Typeable, Exception) |
|
|