module Data.Singletons.Single.Defun (singDefuns) where
import Data.List
import Data.Singletons.Names
import Data.Singletons.Promote.Defun
import Data.Singletons.Single.Monad
import Data.Singletons.Single.Type
import Data.Singletons.Util
import Language.Haskell.TH.Desugar
import Language.Haskell.TH.Syntax
singDefuns :: Name
-> NameSpace
-> DCxt
-> [Maybe DKind]
-> Maybe DKind
-> SgM [DDec]
singDefuns :: Name
-> NameSpace -> DCxt -> [Maybe DKind] -> Maybe DKind -> SgM [DDec]
singDefuns n :: Name
n ns :: NameSpace
ns ty_ctxt :: DCxt
ty_ctxt mb_ty_args :: [Maybe DKind]
mb_ty_args mb_ty_res :: Maybe DKind
mb_ty_res =
case [Maybe DKind]
mb_ty_args of
[] -> [DDec] -> SgM [DDec]
forall (f :: * -> *) a. Applicative f => a -> f a
pure []
_ -> do DCxt
sty_ctxt <- (DKind -> SgM DKind) -> DCxt -> SgM DCxt
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM DKind -> SgM DKind
singPred DCxt
ty_ctxt
Int -> DCxt -> [DTyVarBndr] -> [Maybe DKind] -> SgM [DDec]
go 0 DCxt
sty_ctxt [] [Maybe DKind]
mb_ty_args
where
num_ty_args :: Int
num_ty_args :: Int
num_ty_args = [Maybe DKind] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Maybe DKind]
mb_ty_args
go :: Int -> DCxt -> [DTyVarBndr] -> [Maybe DKind] -> SgM [DDec]
go :: Int -> DCxt -> [DTyVarBndr] -> [Maybe DKind] -> SgM [DDec]
go sym_num :: Int
sym_num sty_ctxt :: DCxt
sty_ctxt tvbs :: [DTyVarBndr]
tvbs mb_tyss :: [Maybe DKind]
mb_tyss
| Int
sym_num Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
num_ty_args
, mb_ty :: Maybe DKind
mb_ty:mb_tys :: [Maybe DKind]
mb_tys <- [Maybe DKind]
mb_tyss
= do Name
new_tvb_name <- String -> SgM Name
forall (m :: * -> *). Quasi m => String -> m Name
qNewName "d"
let new_tvb :: DTyVarBndr
new_tvb = Name -> Maybe DKind -> DTyVarBndr
inferMaybeKindTV Name
new_tvb_name Maybe DKind
mb_ty
[DDec]
insts <- Int -> DCxt -> [DTyVarBndr] -> [Maybe DKind] -> SgM [DDec]
go (Int
sym_num Int -> Int -> Int
forall a. Num a => a -> a -> a
+ 1) DCxt
sty_ctxt ([DTyVarBndr]
tvbs [DTyVarBndr] -> [DTyVarBndr] -> [DTyVarBndr]
forall a. [a] -> [a] -> [a]
++ [DTyVarBndr
new_tvb]) [Maybe DKind]
mb_tys
[DDec] -> SgM [DDec]
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([DDec] -> SgM [DDec]) -> [DDec] -> SgM [DDec]
forall a b. (a -> b) -> a -> b
$ [DDec]
new_insts [DDec] -> [DDec] -> [DDec]
forall a. [a] -> [a] -> [a]
++ [DDec]
insts
| Bool
otherwise
= [DDec] -> SgM [DDec]
forall (f :: * -> *) a. Applicative f => a -> f a
pure []
where
sing_fun_num :: Int
sing_fun_num :: Int
sing_fun_num = Int
num_ty_args Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
sym_num
mk_sing_fun_expr :: DExp -> DExp
mk_sing_fun_expr :: DExp -> DExp
mk_sing_fun_expr sing_expr :: DExp
sing_expr =
(DExp -> Name -> DExp) -> DExp -> [Name] -> DExp
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\f :: DExp
f tvb_n :: Name
tvb_n -> DExp
f DExp -> DExp -> DExp
`DAppE` (Name -> DExp
DVarE Name
singMethName DExp -> DKind -> DExp
`DAppTypeE` Name -> DKind
DVarT Name
tvb_n))
DExp
sing_expr
((DTyVarBndr -> Name) -> [DTyVarBndr] -> [Name]
forall a b. (a -> b) -> [a] -> [b]
map DTyVarBndr -> Name
extractTvbName [DTyVarBndr]
tvbs)
singI_ctxt :: DCxt
singI_ctxt :: DCxt
singI_ctxt = (DTyVarBndr -> DKind) -> [DTyVarBndr] -> DCxt
forall a b. (a -> b) -> [a] -> [b]
map (DKind -> DKind -> DKind
DAppT (Name -> DKind
DConT Name
singIName) (DKind -> DKind) -> (DTyVarBndr -> DKind) -> DTyVarBndr -> DKind
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DTyVarBndr -> DKind
tvbToType) [DTyVarBndr]
tvbs
mk_inst_ty :: DType -> DType
mk_inst_ty :: DKind -> DKind
mk_inst_ty inst_head :: DKind
inst_head
= case Maybe DKind
mb_inst_kind of
Just inst_kind :: DKind
inst_kind -> DKind
inst_head DKind -> DKind -> DKind
`DSigT` DKind
inst_kind
Nothing -> DKind
inst_head
tvb_tys :: [DType]
tvb_tys :: DCxt
tvb_tys = (DTyVarBndr -> DKind) -> [DTyVarBndr] -> DCxt
forall a b. (a -> b) -> [a] -> [b]
map DTyVarBndr -> DKind
dTyVarBndrToDType [DTyVarBndr]
tvbs
mb_inst_kind :: Maybe DType
mb_inst_kind :: Maybe DKind
mb_inst_kind = (Maybe DKind -> Maybe DKind -> Maybe DKind)
-> Maybe DKind -> [Maybe DKind] -> Maybe DKind
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Maybe DKind -> Maybe DKind -> Maybe DKind
buildTyFunArrow_maybe Maybe DKind
mb_ty_res [Maybe DKind]
mb_tyss
new_insts :: [DDec]
new_insts :: [DDec]
new_insts = [Maybe Overlap
-> Maybe [DTyVarBndr] -> DCxt -> DKind -> [DDec] -> DDec
DInstanceD Maybe Overlap
forall a. Maybe a
Nothing Maybe [DTyVarBndr]
forall a. Maybe a
Nothing
(DCxt
sty_ctxt DCxt -> DCxt -> DCxt
forall a. [a] -> [a] -> [a]
++ DCxt
singI_ctxt)
(Name -> DKind
DConT Name
singIName DKind -> DKind -> DKind
`DAppT` DKind -> DKind
mk_inst_ty DKind
defun_inst_ty)
[DLetDec -> DDec
DLetDec (DLetDec -> DDec) -> DLetDec -> DDec
forall a b. (a -> b) -> a -> b
$ DPat -> DExp -> DLetDec
DValD (Name -> DPat
DVarP Name
singMethName)
(DExp -> DLetDec) -> DExp -> DLetDec
forall a b. (a -> b) -> a -> b
$ Int -> DKind -> DExp -> DExp
wrapSingFun Int
sing_fun_num DKind
defun_inst_ty
(DExp -> DExp) -> DExp -> DExp
forall a b. (a -> b) -> a -> b
$ DExp -> DExp
mk_sing_fun_expr DExp
sing_exp ]]
where
defun_inst_ty :: DType
defun_inst_ty :: DKind
defun_inst_ty = DKind -> DCxt -> DKind
foldType (Name -> DKind
DConT (Name -> Int -> Name
promoteTySym Name
n Int
sym_num)) DCxt
tvb_tys
sing_exp :: DExp
sing_exp :: DExp
sing_exp = case NameSpace
ns of
DataName -> Name -> DExp
DConE (Name -> DExp) -> Name -> DExp
forall a b. (a -> b) -> a -> b
$ Name -> Name
singDataConName Name
n
_ -> Name -> DExp
DVarE (Name -> DExp) -> Name -> DExp
forall a b. (a -> b) -> a -> b
$ Name -> Name
singValName Name
n