@@ -8,14 +8,16 @@ module QueryType (
88 instantiateDataDef , instantiateDepPairTy , instantiatePi , instantiateTabPi ,
99 litType , lamExprTy ,
1010 numNaryPiArgs , naryLamExprType ,
11- oneEffect , projectLength , sourceNameType , typeAsBinderNest , typeBinOp
11+ oneEffect , projectLength , sourceNameType , typeAsBinderNest , typeBinOp ,
12+ isSingletonType , singletonTypeVal ,
1213 ) where
1314
1415import Control.Monad
1516import Data.Foldable (toList )
1617import Data.List (elemIndex )
1718import qualified Data.List.NonEmpty as NE
1819import qualified Data.Map.Strict as M
20+ import Data.Maybe (isJust )
1921import qualified Data.Set as S
2022
2123import CheapReduction (cheapNormalize )
@@ -795,3 +797,53 @@ rwsFunEffects rws f = getTypeSubst f >>= \case
795797
796798deleteEff :: Effect n -> EffectRow n -> EffectRow n
797799deleteEff eff (EffectRow effs t) = EffectRow (S. delete eff effs) t
800+
801+ -- === singleton types ===
802+
803+ -- The following implementation should be valid:
804+ -- isSingletonType :: EnvReader m => Type n -> m n Bool
805+ -- isSingletonType ty =
806+ -- singletonTypeVal ty >>= \case
807+ -- Nothing -> return False
808+ -- Just _ -> return True
809+ -- But a separate implementation doesn't have to go under binders,
810+ -- because it doesn't have to reconstruct the singleton value (which
811+ -- may be type annotated and whose type may refer to names).
812+
813+ isSingletonType :: Type n -> Bool
814+ isSingletonType topTy = isJust $ checkIsSingleton topTy
815+ where
816+ checkIsSingleton :: Type n -> Maybe ()
817+ checkIsSingleton ty = case ty of
818+ Pi (PiType _ Pure body) -> checkIsSingleton body
819+ TabPi (TabPiType _ body) -> checkIsSingleton body
820+ StaticRecordTy items -> mapM_ checkIsSingleton items
821+ TC con -> case con of
822+ ProdType tys -> mapM_ checkIsSingleton tys
823+ _ -> Nothing
824+ _ -> Nothing
825+
826+ singletonTypeVal :: EnvReader m => Type n -> m n (Maybe (Atom n ))
827+ singletonTypeVal ty = liftEnvReaderT $
828+ runSubstReaderT idSubst $ singletonTypeValRec ty
829+ {-# INLINE singletonTypeVal #-}
830+
831+ -- TODO: TypeCon with a single case?
832+ singletonTypeValRec :: Type i
833+ -> SubstReaderT Name (EnvReaderT Maybe ) i o (Atom o )
834+ singletonTypeValRec ty = case ty of
835+ Pi (PiType b Pure body) ->
836+ substBinders b \ (PiBinder b' ty' arr) -> do
837+ body' <- singletonTypeValRec body
838+ return $ Lam $ LamExpr (LamBinder b' ty' arr Pure ) $ AtomicBlock body'
839+ TabPi (TabPiType b body) ->
840+ substBinders b \ b' -> do
841+ body' <- singletonTypeValRec body
842+ return $ TabLam $ TabLamExpr b' $ AtomicBlock body'
843+ StaticRecordTy items -> Record <$> traverse singletonTypeValRec items
844+ TC con -> case con of
845+ ProdType tys -> ProdVal <$> traverse singletonTypeValRec tys
846+ _ -> notASingleton
847+ _ -> notASingleton
848+ where notASingleton = fail " not a singleton type"
849+
0 commit comments