diff options
-rw-r--r-- | CHANGES.md | 2 | ||||
-rw-r--r-- | haddock-api/src/Haddock/Backends/LaTeX.hs | 32 | ||||
-rw-r--r-- | haddock-api/src/Haddock/Backends/Xhtml.hs | 4 | ||||
-rw-r--r-- | haddock-api/src/Haddock/Backends/Xhtml/Decl.hs | 56 | ||||
-rw-r--r-- | haddock-api/src/Haddock/Backends/Xhtml/Layout.hs | 4 | ||||
-rw-r--r-- | haddock-api/src/Haddock/GhcUtils.hs | 14 | ||||
-rw-r--r-- | haddock-api/src/Haddock/Interface/AttachInstances.hs | 11 | ||||
-rw-r--r-- | haddock-api/src/Haddock/Interface/Create.hs | 183 | ||||
-rw-r--r-- | haddock-api/src/Haddock/Interface/Rename.hs | 12 | ||||
-rw-r--r-- | haddock-api/src/Haddock/InterfaceFile.hs | 8 | ||||
-rw-r--r-- | haddock-api/src/Haddock/Types.hs | 50 | ||||
-rw-r--r-- | html-test/ref/BundledPatterns.html | 474 | ||||
-rw-r--r-- | html-test/ref/BundledPatterns2.html | 472 | ||||
-rw-r--r-- | html-test/src/BundledPatterns.hs | 110 | ||||
-rw-r--r-- | html-test/src/BundledPatterns2.hs | 10 |
15 files changed, 1329 insertions, 113 deletions
@@ -4,6 +4,8 @@ * Synopsis is working again (#599) + * Support for bundled pattern synonyms (#494, #551, #626) + ## Changes in version 2.17.4 * Fix 'internal error: links: UnhelpfulSpan' (#554, #565) diff --git a/haddock-api/src/Haddock/Backends/LaTeX.hs b/haddock-api/src/Haddock/Backends/LaTeX.hs index 53cfccff..18660b3f 100644 --- a/haddock-api/src/Haddock/Backends/LaTeX.hs +++ b/haddock-api/src/Haddock/Backends/LaTeX.hs @@ -227,8 +227,8 @@ isExportModule _ = Nothing processExport :: ExportItem DocName -> LaTeX processExport (ExportGroup lev _id0 doc) = ppDocGroup lev (docToLaTeX doc) -processExport (ExportDecl decl doc subdocs insts fixities _splice) - = ppDecl decl doc insts subdocs fixities +processExport (ExportDecl decl pats doc subdocs insts fixities _splice) + = ppDecl decl pats doc insts subdocs fixities processExport (ExportNoDecl y []) = ppDocName y processExport (ExportNoDecl y subs) @@ -278,16 +278,17 @@ moduleBasename mdl = map (\c -> if c == '.' then '-' else c) ppDecl :: LHsDecl DocName + -> [(HsDecl DocName,DocForDecl DocName)] -> DocForDecl DocName -> [DocInstance DocName] -> [(DocName, DocForDecl DocName)] -> [(DocName, Fixity)] -> LaTeX -ppDecl (L loc decl) (doc, fnArgsDoc) instances subdocs _fixities = case decl of +ppDecl (L loc decl) pats (doc, fnArgsDoc) instances subdocs _fixities = case decl of TyClD d@(FamDecl {}) -> ppTyFam False loc doc d unicode TyClD d@(DataDecl {}) - -> ppDataDecl instances subdocs loc (Just doc) d unicode + -> ppDataDecl pats instances subdocs loc (Just doc) d unicode TyClD d@(SynDecl {}) -> ppTySyn loc (doc, fnArgsDoc) d unicode -- Family instances happen via FamInst now -- TyClD d@(TySynonym {}) @@ -565,11 +566,11 @@ lookupAnySubdoc n subdocs = case lookup n subdocs of ------------------------------------------------------------------------------- -ppDataDecl :: [DocInstance DocName] -> +ppDataDecl :: [(HsDecl DocName,DocForDecl DocName)] -> [DocInstance DocName] -> [(DocName, DocForDecl DocName)] -> SrcSpan -> Maybe (Documentation DocName) -> TyClDecl DocName -> Bool -> LaTeX -ppDataDecl instances subdocs _loc doc dataDecl unicode +ppDataDecl pats instances subdocs _loc doc dataDecl unicode = declWithDoc (ppDataHeader dataDecl unicode <+> whereBit) (if null body then Nothing else Just (vcat body)) @@ -579,10 +580,12 @@ ppDataDecl instances subdocs _loc doc dataDecl unicode cons = dd_cons (tcdDataDefn dataDecl) resTy = (unLoc . head) cons - body = catMaybes [constrBit, doc >>= documentationToLaTeX] + body = catMaybes [constrBit,patternBit, doc >>= documentationToLaTeX] (whereBit, leaders) - | null cons = (empty,[]) + | null cons + , null pats = (empty,[]) + | null cons = (decltt (keyword "where"), repeat empty) | otherwise = case resTy of ConDeclGADT{} -> (decltt (keyword "where"), repeat empty) _ -> (empty, (decltt (text "=") : repeat (decltt (text "|")))) @@ -594,6 +597,19 @@ ppDataDecl instances subdocs _loc doc dataDecl unicode vcat (zipWith (ppSideBySideConstr subdocs unicode) leaders cons) $$ text "\\end{tabulary}\\par" + patternBit + | null cons = Nothing + | otherwise = Just $ + text "\\haddockbeginconstrs" $$ + vcat [ hsep [ keyword "pattern" + , hsep $ punctuate comma $ map (ppDocBinder . unLoc) lnames + , dcolon unicode + , ppLType unicode (hsSigType ty) + ] <-> rDoc (fmap _doc . combineDocumentation . fst $ d) + | (SigD (PatSynSig lnames ty),d) <- pats + ] $$ + text "\\end{tabulary}\\par" + instancesBit = ppDocInstances unicode instances diff --git a/haddock-api/src/Haddock/Backends/Xhtml.hs b/haddock-api/src/Haddock/Backends/Xhtml.hs index 34ecc5b8..249389b9 100644 --- a/haddock-api/src/Haddock/Backends/Xhtml.hs +++ b/haddock-api/src/Haddock/Backends/Xhtml.hs @@ -604,8 +604,8 @@ processExport :: Bool -> LinksInfo -> Bool -> Qualification processExport _ _ _ _ ExportDecl { expItemDecl = L _ (InstD _) } = Nothing -- Hide empty instances processExport summary _ _ qual (ExportGroup lev id0 doc) = nothingIf summary $ groupHeading lev id0 << docToHtml (Just id0) qual (mkMeta doc) -processExport summary links unicode qual (ExportDecl decl doc subdocs insts fixities splice) - = processDecl summary $ ppDecl summary links decl doc insts fixities subdocs splice unicode qual +processExport summary links unicode qual (ExportDecl decl pats doc subdocs insts fixities splice) + = processDecl summary $ ppDecl summary links decl pats doc insts fixities subdocs splice unicode qual processExport summary _ _ qual (ExportNoDecl y []) = processDeclOneLiner summary $ ppDocName qual Prefix True y processExport summary _ _ qual (ExportNoDecl y subs) diff --git a/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs b/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs index 035c8e9e..716050fa 100644 --- a/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs +++ b/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs @@ -41,11 +41,12 @@ import BooleanFormula import RdrName ( rdrNameOcc ) ppDecl :: Bool -> LinksInfo -> LHsDecl DocName - -> DocForDecl DocName -> [DocInstance DocName] -> [(DocName, Fixity)] + -> [(HsDecl DocName, DocForDecl DocName)] + -> DocForDecl DocName -> [DocInstance DocName] -> [(DocName, Fixity)] -> [(DocName, DocForDecl DocName)] -> Splice -> Unicode -> Qualification -> Html -ppDecl summ links (L loc decl) (mbDoc, fnArgsDoc) instances fixities subdocs splice unicode qual = case decl of +ppDecl summ links (L loc decl) pats (mbDoc, fnArgsDoc) instances fixities subdocs splice unicode qual = case decl of TyClD (FamDecl d) -> ppTyFam summ False links instances fixities loc mbDoc d splice unicode qual - TyClD d@(DataDecl {}) -> ppDataDecl summ links instances fixities subdocs loc mbDoc d splice unicode qual + TyClD d@(DataDecl {}) -> ppDataDecl summ links instances fixities subdocs loc mbDoc d pats splice unicode qual TyClD d@(SynDecl {}) -> ppTySyn summ links fixities loc (mbDoc, fnArgsDoc) d splice unicode qual TyClD d@(ClassDecl {}) -> ppClassDecl summ links instances fixities loc mbDoc subdocs d splice unicode qual SigD (TypeSig lnames lty) -> ppLFunSig summ links loc (mbDoc, fnArgsDoc) lnames @@ -613,7 +614,7 @@ ppInstHead links splice unicode qual mdoc origin orphan no ihd@(InstHead {..}) = , [subFamInstDetails iid pdecl]) where pdata = keyword "data" <+> typ - pdecl = pdata <+> ppShortDataDecl False True dd unicode qual + pdecl = pdata <+> ppShortDataDecl False True dd [] unicode qual where iid = instanceId origin no orphan ihd typ = ppAppNameTypes ihdClsName ihdKinds ihdTypes unicode qual @@ -662,20 +663,23 @@ instanceId origin no orphan ihd = concat $ -- TODO: print contexts -ppShortDataDecl :: Bool -> Bool -> TyClDecl DocName -> Unicode -> Qualification -> Html -ppShortDataDecl summary dataInst dataDecl unicode qual +ppShortDataDecl :: Bool -> Bool -> TyClDecl DocName + -> [(HsDecl DocName,DocForDecl DocName)] + -> Unicode -> Qualification -> Html +ppShortDataDecl summary dataInst dataDecl pats unicode qual - | [] <- cons = dataHeader + | [] <- cons + , [] <- pats = dataHeader - | [lcon] <- cons, isH98, + | [lcon] <- cons, [] <- pats, isH98, (cHead,cBody,cFoot) <- ppShortConstrParts summary dataInst (unLoc lcon) unicode qual = (dataHeader <+> equals <+> cHead) +++ cBody +++ cFoot - | isH98 = dataHeader - +++ shortSubDecls dataInst (zipWith doConstr ('=':repeat '|') cons) + | [] <- pats, isH98 = dataHeader + +++ shortSubDecls dataInst (zipWith doConstr ('=':repeat '|') cons ++ pats1) | otherwise = (dataHeader <+> keyword "where") - +++ shortSubDecls dataInst (map doGADTConstr cons) + +++ shortSubDecls dataInst (map doGADTConstr cons ++ pats1) where dataHeader @@ -689,16 +693,25 @@ ppShortDataDecl summary dataInst dataDecl unicode qual ConDeclH98 {} -> True ConDeclGADT{} -> False + pats1 = [ hsep [ keyword "pattern" + , hsep $ punctuate comma $ map (ppBinder summary . getOccName) lnames + , dcolon unicode + , ppLType unicode qual (hsSigType typ) + ] + | (SigD (PatSynSig lnames typ),_) <- pats + ] + ppDataDecl :: Bool -> LinksInfo -> [DocInstance DocName] -> [(DocName, Fixity)] -> [(DocName, DocForDecl DocName)] -> SrcSpan -> Documentation DocName -> TyClDecl DocName -> + [(HsDecl DocName,DocForDecl DocName)] -> Splice -> Unicode -> Qualification -> Html -ppDataDecl summary links instances fixities subdocs loc doc dataDecl +ppDataDecl summary links instances fixities subdocs loc doc dataDecl pats splice unicode qual - | summary = ppShortDataDecl summary False dataDecl unicode qual - | otherwise = header_ +++ docSection Nothing qual doc +++ constrBit +++ instancesBit + | summary = ppShortDataDecl summary False dataDecl pats unicode qual + | otherwise = header_ +++ docSection Nothing qual doc +++ constrBit +++ patternBit +++ instancesBit where docname = tcdName dataDecl @@ -713,7 +726,9 @@ ppDataDecl summary links instances fixities subdocs loc doc dataDecl fix = ppFixities (filter (\(n,_) -> n == docname) fixities) qual whereBit - | null cons = noHtml + | null cons + , null pats = noHtml + | null cons = keyword "where" | otherwise = if isH98 then noHtml else keyword "where" constrBit = subConstructors qual @@ -723,6 +738,17 @@ ppDataDecl summary links instances fixities subdocs loc doc dataDecl (map unLoc (getConNames (unLoc c)))) fixities ] + patternBit = subPatterns qual + [ (hsep [ keyword "pattern" + , hsep $ punctuate comma $ map (ppBinder summary . getOccName) lnames + , dcolon unicode + , ppLType unicode qual (hsSigType typ) + ] <+> ppFixities subfixs qual + ,combineDocumentation (fst d), []) + | (SigD (PatSynSig lnames typ),d) <- pats + , let subfixs = filter (\(n,_) -> any (\cn -> cn == n) (map unLoc lnames)) fixities + ] + instancesBit = ppInstances links (OriginData docname) instances splice unicode qual diff --git a/haddock-api/src/Haddock/Backends/Xhtml/Layout.hs b/haddock-api/src/Haddock/Backends/Xhtml/Layout.hs index 41457f72..6993c7f6 100644 --- a/haddock-api/src/Haddock/Backends/Xhtml/Layout.hs +++ b/haddock-api/src/Haddock/Backends/Xhtml/Layout.hs @@ -29,6 +29,7 @@ module Haddock.Backends.Xhtml.Layout ( subArguments, subAssociatedTypes, subConstructors, + subPatterns, subEquations, subFields, subInstances, subOrphanInstances, @@ -180,6 +181,9 @@ subAssociatedTypes = divSubDecls "associated-types" "Associated Types" . subBloc subConstructors :: Qualification -> [SubDecl] -> Html subConstructors qual = divSubDecls "constructors" "Constructors" . subTable qual +subPatterns :: Qualification -> [SubDecl] -> Html +subPatterns qual = divSubDecls "bundled-patterns" "Bundled Patterns" . subTable qual + subFields :: Qualification -> [SubDecl] -> Html subFields qual = divSubDecls "fields" "Fields" . subDlist qual diff --git a/haddock-api/src/Haddock/GhcUtils.hs b/haddock-api/src/Haddock/GhcUtils.hs index 4280cd80..02867833 100644 --- a/haddock-api/src/Haddock/GhcUtils.hs +++ b/haddock-api/src/Haddock/GhcUtils.hs @@ -1,4 +1,4 @@ -{-# LANGUAGE FlexibleInstances, ViewPatterns #-} +{-# LANGUAGE BangPatterns, FlexibleInstances, ViewPatterns #-} {-# OPTIONS_GHC -fno-warn-orphans #-} {-# OPTIONS_HADDOCK hide #-} ----------------------------------------------------------------------------- @@ -21,6 +21,7 @@ import Control.Arrow import Exception import Outputable import Name +import NameSet import Lexeme import Module import HscTypes @@ -135,6 +136,17 @@ declATs _ = [] pretty :: Outputable a => DynFlags -> a -> String pretty = showPpr +nubByName :: (a -> Name) -> [a] -> [a] +nubByName f ns = go emptyNameSet ns + where + go !_ [] = [] + go !s (x:xs) + | y `elemNameSet` s = go s xs + | otherwise = let !s' = extendNameSet s y + in x : go s' xs + where + y = f x + ------------------------------------------------------------------------------- -- * Located ------------------------------------------------------------------------------- diff --git a/haddock-api/src/Haddock/Interface/AttachInstances.hs b/haddock-api/src/Haddock/Interface/AttachInstances.hs index d5d74819..7a3182b8 100644 --- a/haddock-api/src/Haddock/Interface/AttachInstances.hs +++ b/haddock-api/src/Haddock/Interface/AttachInstances.hs @@ -21,7 +21,6 @@ import Haddock.GhcUtils import Control.Arrow hiding ((<+>)) import Data.List import Data.Ord (comparing) -import Data.Function (on) import Data.Maybe ( maybeToList, mapMaybe ) import qualified Data.Map as Map import qualified Data.Set as Set @@ -109,13 +108,17 @@ attachToExportItem expInfo iface ifaceMap instIfaceMap export = return $ e { expItemInstances = insts } e -> return e where - attachFixities e@ExportDecl{ expItemDecl = L _ d } = e { expItemFixities = - nubBy ((==) `on` fst) $ expItemFixities e ++ + attachFixities e@ExportDecl{ expItemDecl = L _ d + , expItemPats = patsyns + } = e { expItemFixities = + nubByName fst $ expItemFixities e ++ [ (n',f) | n <- getMainDeclBinder d , Just subs <- [instLookup instSubMap n iface ifaceMap instIfaceMap] - , n' <- n : subs + , n' <- n : (subs ++ patsyn_names) , Just f <- [instLookup instFixMap n' iface ifaceMap instIfaceMap] ] } + where + patsyn_names = concatMap (getMainDeclBinder . fst) patsyns attachFixities e = e -- spanName: attach the location to the name that is the same file as the instance location diff --git a/haddock-api/src/Haddock/Interface/Create.hs b/haddock-api/src/Haddock/Interface/Create.hs index 36b0b7bb..0984894d 100644 --- a/haddock-api/src/Haddock/Interface/Create.hs +++ b/haddock-api/src/Haddock/Interface/Create.hs @@ -42,7 +42,7 @@ import Control.Arrow (second) import Control.DeepSeq (force) import Control.Exception (evaluate) import Control.Monad -import Data.Function (on) +import Data.Traversable import qualified Packages import qualified Module @@ -81,7 +81,10 @@ createInterface tm flags modMap instIfaceMap = do !fam_instances = md_fam_insts md !exportedNames = modInfoExports mi - (TcGblEnv {tcg_rdr_env = gre, tcg_warns = warnings}, md) = tm_internals_ tm + (TcGblEnv { tcg_rdr_env = gre + , tcg_warns = warnings + , tcg_patsyns = patsyns + }, md) = tm_internals_ tm -- The renamed source should always be available to us, but it's best -- to be on the safe side. @@ -101,6 +104,28 @@ createInterface tm flags modMap instIfaceMap = do (!info, mbDoc) <- liftErrMsg $ processModuleHeader dflags gre safety mayDocHeader let declsWithDocs = topDecls group_ + + exports0 = fmap (reverse . map unLoc) mayExports + exports + | OptIgnoreExports `elem` opts = Nothing + | otherwise = exports0 + warningMap = mkWarningMap dflags warnings gre exportedNames + + localBundledPatSyns :: Map Name [Name] + localBundledPatSyns = + case exports of + Nothing -> M.empty + Just ies -> + M.map (nubByName id) $ + M.fromListWith (++) [ (ieWrappedName ty_name, bundled_patsyns) + | IEThingWith (L _ ty_name) _ exported _ <- ies + , let bundled_patsyns = + filter is_patsyn (map (ieWrappedName . unLoc) exported) + , not (null bundled_patsyns) + ] + where + is_patsyn name = elemNameSet name (mkNameSet (map getName patsyns)) + fixMap = mkFixMap group_ (decls, _) = unzip declsWithDocs localInsts = filter (nameIsLocalOrFrom sem_mdl) @@ -112,18 +137,12 @@ createInterface tm flags modMap instIfaceMap = do maps@(!docMap, !argMap, !subMap, !declMap, _) = mkMaps dflags gre localInsts declsWithDocs - let exports0 = fmap (reverse . map unLoc) mayExports - exports - | OptIgnoreExports `elem` opts = Nothing - | otherwise = exports0 - warningMap = mkWarningMap dflags warnings gre exportedNames - let allWarnings = M.unions (warningMap : map ifaceWarningMap (M.elems modMap)) -- The MAIN functionality: compute the export items which will -- each be the actual documentation of this module. exportItems <- mkExportItems is_sig modMap mdl sem_mdl allWarnings gre exportedNames decls - maps fixMap splices exports instIfaceMap dflags + maps localBundledPatSyns fixMap splices exports instIfaceMap dflags let !visibleNames = mkVisibleNames maps exportItems opts @@ -147,32 +166,33 @@ createInterface tm flags modMap instIfaceMap = do tokenizedSrc <- mkMaybeTokenizedSrc flags tm return $! Interface { - ifaceMod = mdl - , ifaceIsSig = is_sig - , ifaceOrigFilename = msHsFilePath ms - , ifaceInfo = info - , ifaceDoc = Documentation mbDoc modWarn - , ifaceRnDoc = Documentation Nothing Nothing - , ifaceOptions = opts - , ifaceDocMap = docMap - , ifaceArgMap = argMap - , ifaceRnDocMap = M.empty - , ifaceRnArgMap = M.empty - , ifaceExportItems = prunedExportItems - , ifaceRnExportItems = [] - , ifaceExports = exportedNames - , ifaceVisibleExports = visibleNames - , ifaceDeclMap = declMap - , ifaceSubMap = subMap - , ifaceFixMap = fixMap - , ifaceModuleAliases = aliases - , ifaceInstances = instances - , ifaceFamInstances = fam_instances + ifaceMod = mdl + , ifaceIsSig = is_sig + , ifaceOrigFilename = msHsFilePath ms + , ifaceInfo = info + , ifaceDoc = Documentation mbDoc modWarn + , ifaceRnDoc = Documentation Nothing Nothing + , ifaceOptions = opts + , ifaceDocMap = docMap + , ifaceArgMap = argMap + , ifaceRnDocMap = M.empty + , ifaceRnArgMap = M.empty + , ifaceExportItems = prunedExportItems + , ifaceRnExportItems = [] + , ifaceExports = exportedNames + , ifaceVisibleExports = visibleNames + , ifaceDeclMap = declMap + , ifaceBundledPatSynMap = localBundledPatSyns + , ifaceSubMap = subMap + , ifaceFixMap = fixMap + , ifaceModuleAliases = aliases + , ifaceInstances = instances + , ifaceFamInstances = fam_instances , ifaceOrphanInstances = [] -- Filled in `attachInstances` , ifaceRnOrphanInstances = [] -- Filled in `renameInterface` - , ifaceHaddockCoverage = coverage - , ifaceWarningMap = warningMap - , ifaceTokenizedSrc = tokenizedSrc + , ifaceHaddockCoverage = coverage + , ifaceWarningMap = warningMap + , ifaceTokenizedSrc = tokenizedSrc } -- | Given all of the @import M as N@ declarations in a package, @@ -295,8 +315,9 @@ mkMaps :: DynFlags -> [(LHsDecl Name, [HsDocString])] -> Maps mkMaps dflags gre instances decls = - let (a, b, c, d) = unzip4 $ map mappings decls - in (f' $ map (nubBy ((==) `on` fst)) a , f b, f c, f d, instanceMap) + let + (a, b, c, d) = unzip4 $ map mappings decls + in (f' $ map (nubByName fst) a , f b, f c, f d, instanceMap) where f :: (Ord a, Monoid b) => [[(a, b)]] -> Map a b f = M.fromListWith (<>) . concat @@ -362,7 +383,9 @@ mkMaps dflags gre instances decls = -- | Get all subordinate declarations inside a declaration, and their docs. -- A subordinate declaration is something like the associate type or data -- family of a type class. -subordinates :: InstMap -> HsDecl Name -> [(Name, [HsDocString], Map Int HsDocString)] +subordinates :: InstMap + -> HsDecl Name + -> [(Name, [HsDocString], Map Int HsDocString)] subordinates instMap decl = case decl of InstD (ClsInstD d) -> do DataFamInstDecl { dfid_tycon = L l _ @@ -539,6 +562,7 @@ mkExportItems -> [Name] -- exported names (orig) -> [LHsDecl Name] -- renamed source declarations -> Maps + -> Map Name [Name] -> FixMap -> [SrcSpan] -- splice locations -> Maybe [IE Name] @@ -547,15 +571,21 @@ mkExportItems -> ErrMsgGhc [ExportItem Name] mkExportItems is_sig modMap thisMod semMod warnings gre exportedNames decls - maps@(docMap, argMap, subMap, declMap, instMap) fixMap splices optExports instIfaceMap dflags = + maps@(docMap, argMap, subMap, declMap, instMap) patSynMap fixMap splices optExports instIfaceMap dflags = case optExports of Nothing -> fullModuleContents dflags warnings gre maps fixMap splices decls Just exports -> liftM concat $ mapM lookupExport exports where - lookupExport (IEVar (L _ x)) = declWith $ ieWrappedName x - lookupExport (IEThingAbs (L _ t)) = declWith $ ieWrappedName t - lookupExport (IEThingAll (L _ t)) = declWith $ ieWrappedName t - lookupExport (IEThingWith (L _ t) _ _ _) = declWith $ ieWrappedName t + lookupExport (IEVar (L _ x)) = declWith [] $ ieWrappedName x + lookupExport (IEThingAbs (L _ t)) = declWith [] $ ieWrappedName t + lookupExport (IEThingAll (L _ t)) = do + let name = ieWrappedName t + pats <- findBundledPatterns name + declWith pats name + lookupExport (IEThingWith (L _ t) _ _ _) = do + let name = ieWrappedName t + pats <- findBundledPatterns name + declWith pats name lookupExport (IEModuleContents (L _ m)) = -- TODO: We could get more accurate reporting here if IEModuleContents -- also recorded the actual names that are exported here. We CAN @@ -574,8 +604,8 @@ mkExportItems Nothing -> [] Just doc -> return . ExportDoc $ processDocStringParas dflags gre doc - declWith :: Name -> ErrMsgGhc [ ExportItem Name ] - declWith t = do + declWith :: [(HsDecl Name, DocForDecl Name)] -> Name -> ErrMsgGhc [ ExportItem Name ] + declWith pats t = do r <- findDecl t case r of ([L l (ValD _)], (doc, _)) -> do @@ -612,15 +642,15 @@ mkExportItems -- fromJust is safe since we already checked in guards -- that 't' is a name declared in this declaration. let newDecl = L loc . SigD . fromJust $ filterSigNames (== t) sig - in return [ mkExportDecl t newDecl docs_ ] + in return [ mkExportDecl t newDecl pats docs_ ] L loc (TyClD cl@ClassDecl{}) -> do mdef <- liftGhcToErrMsgGhc $ minimalDef t let sig = maybeToList $ fmap (noLoc . MinimalSig NoSourceText . noLoc . fmap noLoc) mdef return [ mkExportDecl t - (L loc $ TyClD cl { tcdSigs = sig ++ tcdSigs cl }) docs_ ] + (L loc $ TyClD cl { tcdSigs = sig ++ tcdSigs cl }) pats docs_ ] - _ -> return [ mkExportDecl t decl docs_ ] + _ -> return [ mkExportDecl t decl pats docs_ ] -- Declaration from another package ([], _) -> do @@ -637,20 +667,24 @@ mkExportItems liftErrMsg $ tell ["Warning: Couldn't find .haddock for export " ++ pretty dflags t] let subs_ = [ (n, noDocForDecl) | (n, _, _) <- subordinates instMap (unLoc decl) ] - return [ mkExportDecl t decl (noDocForDecl, subs_) ] + return [ mkExportDecl t decl pats (noDocForDecl, subs_) ] Just iface -> - return [ mkExportDecl t decl (lookupDocs t warnings (instDocMap iface) (instArgMap iface) (instSubMap iface)) ] + return [ mkExportDecl t decl pats (lookupDocs t warnings (instDocMap iface) (instArgMap iface) (instSubMap iface)) ] _ -> return [] - mkExportDecl :: Name -> LHsDecl Name -> (DocForDecl Name, [(Name, DocForDecl Name)]) -> ExportItem Name - mkExportDecl name decl (doc, subs) = decl' + mkExportDecl :: Name -> LHsDecl Name -> [(HsDecl Name, DocForDecl Name)] + -> (DocForDecl Name, [(Name, DocForDecl Name)]) -> ExportItem Name + mkExportDecl name decl pats (doc, subs) = decl' where - decl' = ExportDecl (restrictTo sub_names (extractDecl name decl)) doc subs' [] fixities False + decl' = ExportDecl (restrictTo sub_names (extractDecl name decl)) pats' doc subs' [] fixities False subs' = filter (isExported . fst) subs + pats' = [ d | d@(patsyn_decl, _) <- pats + , all isExported (getMainDeclBinder patsyn_decl) ] sub_names = map fst subs' - fixities = [ (n, f) | n <- name:sub_names, Just f <- [M.lookup n fixMap] ] + pat_names = [ n | (patsyn_decl, _) <- pats', n <- getMainDeclBinder patsyn_decl] + fixities = [ (n, f) | n <- name:sub_names++pat_names, Just f <- [M.lookup n fixMap] ] exportedNameSet = mkNameSet exportedNames isExported n = elemNameSet n exportedNameSet @@ -684,6 +718,40 @@ mkExportItems where m = nameModule n + findBundledPatterns :: Name -> ErrMsgGhc [(HsDecl Name, DocForDecl Name)] + findBundledPatterns t = + let + m = nameModule t + + local_bundled_patsyns = + M.findWithDefault [] t patSynMap + + iface_bundled_patsyns + | Just iface <- M.lookup (semToIdMod (moduleUnitId thisMod) m) modMap + , Just patsyns <- M.lookup t (ifaceBundledPatSynMap iface) + = patsyns + + | Just iface <- M.lookup m instIfaceMap + , Just patsyns <- M.lookup t (instBundledPatSynMap iface) + = patsyns + + | otherwise + = [] + + patsyn_decls = do + for (local_bundled_patsyns ++ iface_bundled_patsyns) $ \patsyn_name -> do + -- call declWith here so we don't have to prepare the pattern synonym for + -- showing ourselves. + export_items <- declWith [] patsyn_name + pure [ (unLoc patsyn_decl, patsyn_doc) + | ExportDecl { + expItemDecl = patsyn_decl + , expItemMbDoc = patsyn_doc + } <- export_items + ] + + in concat <$> patsyn_decls + -- | Given a 'Module' from a 'Name', convert it into a 'Module' that -- we can actually find in the 'IfaceMap'. semToIdMod :: UnitId -> Module -> Module @@ -718,7 +786,7 @@ hiValExportItem dflags name nLoc doc splice fixity = do mayDecl <- hiDecl dflags name case mayDecl of Nothing -> return (ExportNoDecl name []) - Just decl -> return (ExportDecl (fixSpan decl) doc [] [] fixities splice) + Just decl -> return (ExportDecl (fixSpan decl) [] doc [] [] fixities splice) where fixSpan (L l t) = L (SrcLoc.combineSrcSpans l nLoc) t fixities = case fixity of @@ -873,12 +941,12 @@ fullModuleContents dflags warnings gre (docMap, argMap, subMap, declMap, instMap fixities name subs = [ (n,f) | n <- name : map fst subs , Just f <- [M.lookup n fixMap] ] - expDecl decl l name = return $ Just (ExportDecl decl doc subs [] (fixities name subs) (l `elem` splices)) + expDecl decl l name = return $ Just (ExportDecl decl [] doc subs [] (fixities name subs) (l `elem` splices)) where (doc, subs) = lookupDocs name warnings docMap argMap subMap expInst decl l name = let (doc, subs) = lookupDocs name warnings docMap argMap subMap in - return $ Just (ExportDecl decl doc subs [] (fixities name subs) (l `elem` splices)) + return $ Just (ExportDecl decl [] doc subs [] (fixities name subs) (l `elem` splices)) -- | Sometimes the declaration we want to export is not the "main" declaration: @@ -958,8 +1026,9 @@ mkVisibleNames (_, _, _, _, instMap) exports opts | otherwise = let ns = concatMap exportName exports in seqList ns `seq` ns where - exportName e@ExportDecl {} = name ++ subs - where subs = map fst (expItemSubDocs e) + exportName e@ExportDecl {} = name ++ subs ++ patsyns + where subs = map fst (expItemSubDocs e) + patsyns = concatMap (getMainDeclBinder . fst) (expItemPats e) name = case unLoc $ expItemDecl e of InstD d -> maybeToList $ M.lookup (getInstLoc d) instMap decl -> getMainDeclBinder decl diff --git a/haddock-api/src/Haddock/Interface/Rename.hs b/haddock-api/src/Haddock/Interface/Rename.hs index b43860fb..5820c61e 100644 --- a/haddock-api/src/Haddock/Interface/Rename.hs +++ b/haddock-api/src/Haddock/Interface/Rename.hs @@ -55,7 +55,7 @@ renameInterface dflags renamingEnv warnings iface = -- combine the missing names and filter out the built-ins, which would -- otherwise always be missing. - missingNames = nub $ filter isExternalName -- XXX: isExternalName filters out too much + missingNames = nubByName id $ filter isExternalName -- XXX: isExternalName filters out too much (missingNames1 ++ missingNames2 ++ missingNames3 ++ missingNames4 ++ missingNames5) @@ -314,6 +314,11 @@ renameInstHead InstHead {..} = do renameLDecl :: LHsDecl Name -> RnM (LHsDecl DocName) renameLDecl (L loc d) = return . L loc =<< renameDecl d +renamePats :: [(HsDecl Name,DocForDecl Name)] -> RnM [(HsDecl DocName,DocForDecl DocName)] +renamePats = mapM + (\(d,doc) -> do { d' <- renameDecl d + ; doc' <- renameDocForDecl doc + ; return (d',doc')}) renameDecl :: HsDecl Name -> RnM (HsDecl DocName) renameDecl decl = case decl of @@ -601,15 +606,16 @@ renameExportItem item = case item of ExportGroup lev id_ doc -> do doc' <- renameDoc doc return (ExportGroup lev id_ doc') - ExportDecl decl doc subs instances fixities splice -> do + ExportDecl decl pats doc subs instances fixities splice -> do decl' <- renameLDecl decl + pats' <- renamePats pats doc' <- renameDocForDecl doc subs' <- mapM renameSub subs instances' <- forM instances renameDocInstance fixities' <- forM fixities $ \(name, fixity) -> do name' <- lookupRn name return (name', fixity) - return (ExportDecl decl' doc' subs' instances' fixities' splice) + return (ExportDecl decl' pats' doc' subs' instances' fixities' splice) ExportNoDecl x subs -> do x' <- lookupRn x subs' <- mapM lookupRn subs diff --git a/haddock-api/src/Haddock/InterfaceFile.hs b/haddock-api/src/Haddock/InterfaceFile.hs index e5c2face..054c1384 100644 --- a/haddock-api/src/Haddock/InterfaceFile.hs +++ b/haddock-api/src/Haddock/InterfaceFile.hs @@ -83,7 +83,7 @@ binaryInterfaceMagic = 0xD0Cface -- binaryInterfaceVersion :: Word16 #if (__GLASGOW_HASKELL__ >= 802) && (__GLASGOW_HASKELL__ < 804) -binaryInterfaceVersion = 30 +binaryInterfaceVersion = 31 binaryInterfaceVersionCompatibility :: [Word16] binaryInterfaceVersionCompatibility = [binaryInterfaceVersion] @@ -373,7 +373,7 @@ instance Binary InterfaceFile where instance Binary InstalledInterface where put_ bh (InstalledInterface modu is_sig info docMap argMap - exps visExps opts subMap fixMap) = do + exps visExps opts subMap patSynMap fixMap) = do put_ bh modu put_ bh is_sig put_ bh info @@ -382,6 +382,7 @@ instance Binary InstalledInterface where put_ bh visExps put_ bh opts put_ bh subMap + put_ bh patSynMap put_ bh fixMap get bh = do @@ -393,10 +394,11 @@ instance Binary InstalledInterface where visExps <- get bh opts <- get bh subMap <- get bh + patSynMap <- get bh fixMap <- get bh return (InstalledInterface modu is_sig info docMap argMap - exps visExps opts subMap fixMap) + exps visExps opts subMap patSynMap fixMap) instance Binary DocOption where diff --git a/haddock-api/src/Haddock/Types.hs b/haddock-api/src/Haddock/Types.hs index 803995cc..bfc8e32b 100644 --- a/haddock-api/src/Haddock/Types.hs +++ b/haddock-api/src/Haddock/Types.hs @@ -103,6 +103,9 @@ data Interface = Interface -- names of subordinate declarations mapped to their parent declarations. , ifaceDeclMap :: !(Map Name [LHsDecl Name]) + -- | Bundled pattern synonym declarations for specific types. + , ifaceBundledPatSynMap :: !(Map Name [Name]) + -- | Documentation of declarations originating from the module (including -- subordinates). , ifaceDocMap :: !(DocMap Name) @@ -158,49 +161,53 @@ type WarningMap = Map Name (Doc Name) data InstalledInterface = InstalledInterface { -- | The module represented by this interface. - instMod :: Module + instMod :: Module -- | Is this a signature? - , instIsSig :: Bool + , instIsSig :: Bool -- | Textual information about the module. - , instInfo :: HaddockModInfo Name + , instInfo :: HaddockModInfo Name -- | Documentation of declarations originating from the module (including -- subordinates). - , instDocMap :: DocMap Name + , instDocMap :: DocMap Name - , instArgMap :: ArgMap Name + , instArgMap :: ArgMap Name -- | All names exported by this module. - , instExports :: [Name] + , instExports :: [Name] -- | All \"visible\" names exported by the module. -- A visible name is a name that will show up in the documentation of the -- module. - , instVisibleExports :: [Name] + , instVisibleExports :: [Name] -- | Haddock options for this module (prune, ignore-exports, etc). - , instOptions :: [DocOption] + , instOptions :: [DocOption] + + , instSubMap :: Map Name [Name] - , instSubMap :: Map Name [Name] - , instFixMap :: Map Name Fixity + , instBundledPatSynMap :: Map Name [Name] + + , instFixMap :: Map Name Fixity } -- | Convert an 'Interface' to an 'InstalledInterface' toInstalledIface :: Interface -> InstalledInterface toInstalledIface interface = InstalledInterface - { instMod = ifaceMod interface - , instIsSig = ifaceIsSig interface - , instInfo = ifaceInfo interface - , instDocMap = ifaceDocMap interface - , instArgMap = ifaceArgMap interface - , instExports = ifaceExports interface - , instVisibleExports = ifaceVisibleExports interface - , instOptions = ifaceOptions interface - , instSubMap = ifaceSubMap interface - , instFixMap = ifaceFixMap interface + { instMod = ifaceMod interface + , instIsSig = ifaceIsSig interface + , instInfo = ifaceInfo interface + , instDocMap = ifaceDocMap interface + , instArgMap = ifaceArgMap interface + , instExports = ifaceExports interface + , instVisibleExports = ifaceVisibleExports interface + , instOptions = ifaceOptions interface + , instSubMap = ifaceSubMap interface + , instBundledPatSynMap = ifaceBundledPatSynMap interface + , instFixMap = ifaceFixMap interface } @@ -217,6 +224,9 @@ data ExportItem name -- | A declaration. expItemDecl :: !(LHsDecl name) + -- | Bundled patterns for a data type declaration + , expItemPats :: ![(HsDecl name, DocForDecl name)] + -- | Maybe a doc comment, and possibly docs for arguments (if this -- decl is a function or type-synonym). , expItemMbDoc :: !(DocForDecl name) diff --git a/html-test/ref/BundledPatterns.html b/html-test/ref/BundledPatterns.html new file mode 100644 index 00000000..bf6c073c --- /dev/null +++ b/html-test/ref/BundledPatterns.html @@ -0,0 +1,474 @@ +<html xmlns="http://www.w3.org/1999/xhtml" +><head + ><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" + /><title + >BundledPatterns</title + ><link href="#" rel="stylesheet" type="text/css" title="Ocean" + /><script src="haddock-util.js" type="text/javascript" + ></script + ><script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS-MML_HTMLorMML" type="text/javascript" + ></script + ><script type="text/javascript" + >// +window.onload = function () {pageLoad();}; +// +</script + ></head + ><body + ><div id="package-header" + ><ul class="links" id="page-menu" + ><li + ><a href="#" + >Contents</a + ></li + ><li + ><a href="#" + >Index</a + ></li + ></ul + ><p class="caption empty" + ></p + ></div + ><div id="content" + ><div id="module-header" + ><table class="info" + ><tr + ><th + >Safe Haskell</th + ><td + >None</td + ></tr + ></table + ><p class="caption" + >BundledPatterns</p + ></div + ><div id="synopsis" + ><p id="control.syn" class="caption expander" onclick="toggleSection('syn')" + >Synopsis</p + ><ul id="section.syn" class="hide" onclick="toggleSection('syn')" + ><li class="src short" + ><span class="keyword" + >data</span + > <a href="#" + >Vec</a + > :: <a href="#" + >Nat</a + > -> <a href="#" + >*</a + > -> <a href="#" + >*</a + > <span class="keyword" + >where</span + ><ul class="subs" + ><li + ><a href="#" + >Nil</a + > :: <a href="#" + >Vec</a + > 0 a</li + ><li + ><span class="keyword" + >pattern</span + > <a href="#" + >(:>)</a + > :: a -> <a href="#" + >Vec</a + > n a -> <a href="#" + >Vec</a + > (n <a href="#" + >+</a + > 1) a</li + ></ul + ></li + ><li class="src short" + ><span class="keyword" + >data</span + > <a href="#" + >RTree</a + > :: <a href="#" + >Nat</a + > -> <a href="#" + >*</a + > -> <a href="#" + >*</a + > <span class="keyword" + >where</span + ><ul class="subs" + ><li + ><span class="keyword" + >pattern</span + > <a href="#" + >LR</a + > :: a -> <a href="#" + >RTree</a + > 0 a</li + ><li + ><span class="keyword" + >pattern</span + > <a href="#" + >BR</a + > :: <a href="#" + >RTree</a + > d a -> <a href="#" + >RTree</a + > d a -> <a href="#" + >RTree</a + > (d <a href="#" + >+</a + > 1) a</li + ></ul + ></li + ></ul + ></div + ><div id="interface" + ><h1 + >Documentation</h1 + ><div class="top" + ><p class="src" + ><span class="keyword" + >data</span + > <a id="t:Vec" class="def" + >Vec</a + > :: <a href="#" + >Nat</a + > -> <a href="#" + >*</a + > -> <a href="#" + >*</a + > <span class="keyword" + >where</span + > <a href="#" class="selflink" + >#</a + ></p + ><div class="doc" + ><p + >Fixed size vectors.</p + ><ul + ><li + >Lists with their length encoded in their type</li + ><li + ><code + ><a href="#" + >Vec</a + ></code + >tor elements have an <strong + >ASCENDING</strong + > subscript starting from 0 and + ending at <code + ><code + ><a href="#" + >length</a + ></code + > - 1</code + >.</li + ></ul + ></div + ><div class="subs constructors" + ><p class="caption" + >Constructors</p + ><table + ><tr + ><td class="src" + ><a id="v:Nil" class="def" + >Nil</a + > :: <a href="#" + >Vec</a + > 0 a</td + ><td class="doc empty" + ></td + ></tr + ></table + ></div + ><div class="subs bundled-patterns" + ><p class="caption" + >Bundled Patterns</p + ><table + ><tr + ><td class="src" + ><span class="keyword" + >pattern</span + > <a id="v::-62-" class="def" + >(:>)</a + > :: a -> <a href="#" + >Vec</a + > n a -> <a href="#" + >Vec</a + > (n <a href="#" + >+</a + > 1) a <span class="fixity" + >infixr 5</span + ><span class="rightedge" + ></span + ></td + ><td class="doc" + ><p + >Add an element to the head of a vector.</p + ><pre class="screen" + ><code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >3:>4:>5:>Nil +</code + ></strong + ><3,4,5> +<code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >let x = 3:>4:>5:>Nil +</code + ></strong + ><code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >:t x +</code + ></strong + >x :: Num a => Vec 3 a +</pre + ><p + >Can be used as a pattern:</p + ><pre class="screen" + ><code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >let f (x :> y :> _) = x + y +</code + ></strong + ><code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >:t f +</code + ></strong + >f :: Num a => Vec ((n + 1) + 1) a -> a +<code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >f (3:>4:>5:>6:>7:>Nil) +</code + ></strong + >7 +</pre + ><p + >Also in conjunctions with (<code + >:<</code + >):</p + ><pre class="screen" + ><code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >let g (a :> b :> (_ :< y :< x)) = a + b + x + y +</code + ></strong + ><code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >:t g +</code + ></strong + >g :: Num a => Vec ((((n + 1) + 1) + 1) + 1) a -> a +<code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >g (1:>2:>3:>4:>5:>Nil) +</code + ></strong + >12 +</pre + ></td + ></tr + ></table + ></div + ></div + ><div class="top" + ><p class="src" + ><span class="keyword" + >data</span + > <a id="t:RTree" class="def" + >RTree</a + > :: <a href="#" + >Nat</a + > -> <a href="#" + >*</a + > -> <a href="#" + >*</a + > <span class="keyword" + >where</span + > <a href="#" class="selflink" + >#</a + ></p + ><div class="doc" + ><p + >Perfect depth binary tree.</p + ><ul + ><li + >Only has elements at the leaf of the tree</li + ><li + >A tree of depth <em + >d</em + > has <em + >2^d</em + > elements.</li + ></ul + ></div + ><div class="subs bundled-patterns" + ><p class="caption" + >Bundled Patterns</p + ><table + ><tr + ><td class="src" + ><span class="keyword" + >pattern</span + > <a id="v:LR" class="def" + >LR</a + > :: a -> <a href="#" + >RTree</a + > 0 a</td + ><td class="doc" + ><p + >Leaf of a perfect depth tree</p + ><pre class="screen" + ><code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >LR 1 +</code + ></strong + >1 +<code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >let x = LR 1 +</code + ></strong + ><code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >:t x +</code + ></strong + >x :: Num a => RTree 0 a +</pre + ><p + >Can be used as a pattern:</p + ><pre class="screen" + ><code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >let f (LR a) (LR b) = a + b +</code + ></strong + ><code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >:t f +</code + ></strong + >f :: Num a => RTree 0 a -> RTree 0 a -> a +<code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >f (LR 1) (LR 2) +</code + ></strong + >3 +</pre + ></td + ></tr + ><tr + ><td class="src" + ><span class="keyword" + >pattern</span + > <a id="v:BR" class="def" + >BR</a + > :: <a href="#" + >RTree</a + > d a -> <a href="#" + >RTree</a + > d a -> <a href="#" + >RTree</a + > (d <a href="#" + >+</a + > 1) a</td + ><td class="doc" + ><p + >Branch of a perfect depth tree</p + ><pre class="screen" + ><code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >BR (LR 1) (LR 2) +</code + ></strong + ><1,2> +<code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >let x = BR (LR 1) (LR 2) +</code + ></strong + ><code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >:t x +</code + ></strong + >x :: Num a => RTree 1 a +</pre + ><p + >Case be used a pattern:</p + ><pre class="screen" + ><code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >let f (BR (LR a) (LR b)) = LR (a + b) +</code + ></strong + ><code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >:t f +</code + ></strong + >f :: Num a => RTree 1 a -> RTree 0 a +<code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >f (BR (LR 1) (LR 2)) +</code + ></strong + >3 +</pre + ></td + ></tr + ></table + ></div + ></div + ></div + ></div + ><div id="footer" + ></div + ></body + ></html +>
\ No newline at end of file diff --git a/html-test/ref/BundledPatterns2.html b/html-test/ref/BundledPatterns2.html new file mode 100644 index 00000000..3d1d4da0 --- /dev/null +++ b/html-test/ref/BundledPatterns2.html @@ -0,0 +1,472 @@ +<html xmlns="http://www.w3.org/1999/xhtml" +><head + ><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" + /><title + >BundledPatterns2</title + ><link href="#" rel="stylesheet" type="text/css" title="Ocean" + /><script src="haddock-util.js" type="text/javascript" + ></script + ><script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS-MML_HTMLorMML" type="text/javascript" + ></script + ><script type="text/javascript" + >// +window.onload = function () {pageLoad();}; +// +</script + ></head + ><body + ><div id="package-header" + ><ul class="links" id="page-menu" + ><li + ><a href="#" + >Contents</a + ></li + ><li + ><a href="#" + >Index</a + ></li + ></ul + ><p class="caption empty" + ></p + ></div + ><div id="content" + ><div id="module-header" + ><table class="info" + ><tr + ><th + >Safe Haskell</th + ><td + >None</td + ></tr + ></table + ><p class="caption" + >BundledPatterns2</p + ></div + ><div id="synopsis" + ><p id="control.syn" class="caption expander" onclick="toggleSection('syn')" + >Synopsis</p + ><ul id="section.syn" class="hide" onclick="toggleSection('syn')" + ><li class="src short" + ><span class="keyword" + >data</span + > <a href="#" + >Vec</a + > :: <a href="#" + >Nat</a + > -> <a href="#" + >*</a + > -> <a href="#" + >*</a + > <span class="keyword" + >where</span + ><ul class="subs" + ><li + ><span class="keyword" + >pattern</span + > <a href="#" + >Empty</a + > :: <a href="#" + >Vec</a + > 0 a</li + ><li + ><span class="keyword" + >pattern</span + > <a href="#" + >(:>)</a + > :: a -> <a href="#" + >Vec</a + > n a -> <a href="#" + >Vec</a + > (n <a href="#" + >+</a + > 1) a</li + ></ul + ></li + ><li class="src short" + ><span class="keyword" + >data</span + > <a href="#" + >RTree</a + > :: <a href="#" + >Nat</a + > -> <a href="#" + >*</a + > -> <a href="#" + >*</a + > <span class="keyword" + >where</span + ><ul class="subs" + ><li + ><span class="keyword" + >pattern</span + > <a href="#" + >LR</a + > :: a -> <a href="#" + >RTree</a + > 0 a</li + ><li + ><span class="keyword" + >pattern</span + > <a href="#" + >BR</a + > :: <a href="#" + >RTree</a + > d a -> <a href="#" + >RTree</a + > d a -> <a href="#" + >RTree</a + > (d <a href="#" + >+</a + > 1) a</li + ></ul + ></li + ></ul + ></div + ><div id="interface" + ><h1 + >Documentation</h1 + ><div class="top" + ><p class="src" + ><span class="keyword" + >data</span + > <a id="t:Vec" class="def" + >Vec</a + > :: <a href="#" + >Nat</a + > -> <a href="#" + >*</a + > -> <a href="#" + >*</a + > <span class="keyword" + >where</span + > <a href="#" class="selflink" + >#</a + ></p + ><div class="doc" + ><p + >Fixed size vectors.</p + ><ul + ><li + >Lists with their length encoded in their type</li + ><li + ><code + ><a href="#" + >Vec</a + ></code + >tor elements have an <strong + >ASCENDING</strong + > subscript starting from 0 and + ending at <code + ><code + ><a href="#" + >length</a + ></code + > - 1</code + >.</li + ></ul + ></div + ><div class="subs bundled-patterns" + ><p class="caption" + >Bundled Patterns</p + ><table + ><tr + ><td class="src" + ><span class="keyword" + >pattern</span + > <a id="v:Empty" class="def" + >Empty</a + > :: <a href="#" + >Vec</a + > 0 a</td + ><td class="doc empty" + ></td + ></tr + ><tr + ><td class="src" + ><span class="keyword" + >pattern</span + > <a id="v::-62-" class="def" + >(:>)</a + > :: a -> <a href="#" + >Vec</a + > n a -> <a href="#" + >Vec</a + > (n <a href="#" + >+</a + > 1) a <span class="fixity" + >infixr 5</span + ><span class="rightedge" + ></span + ></td + ><td class="doc" + ><p + >Add an element to the head of a vector.</p + ><pre class="screen" + ><code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >3:>4:>5:>Nil +</code + ></strong + ><3,4,5> +<code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >let x = 3:>4:>5:>Nil +</code + ></strong + ><code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >:t x +</code + ></strong + >x :: Num a => Vec 3 a +</pre + ><p + >Can be used as a pattern:</p + ><pre class="screen" + ><code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >let f (x :> y :> _) = x + y +</code + ></strong + ><code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >:t f +</code + ></strong + >f :: Num a => Vec ((n + 1) + 1) a -> a +<code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >f (3:>4:>5:>6:>7:>Nil) +</code + ></strong + >7 +</pre + ><p + >Also in conjunctions with (<code + >:<</code + >):</p + ><pre class="screen" + ><code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >let g (a :> b :> (_ :< y :< x)) = a + b + x + y +</code + ></strong + ><code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >:t g +</code + ></strong + >g :: Num a => Vec ((((n + 1) + 1) + 1) + 1) a -> a +<code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >g (1:>2:>3:>4:>5:>Nil) +</code + ></strong + >12 +</pre + ></td + ></tr + ></table + ></div + ></div + ><div class="top" + ><p class="src" + ><span class="keyword" + >data</span + > <a id="t:RTree" class="def" + >RTree</a + > :: <a href="#" + >Nat</a + > -> <a href="#" + >*</a + > -> <a href="#" + >*</a + > <span class="keyword" + >where</span + > <a href="#" class="selflink" + >#</a + ></p + ><div class="doc" + ><p + >Perfect depth binary tree.</p + ><ul + ><li + >Only has elements at the leaf of the tree</li + ><li + >A tree of depth <em + >d</em + > has <em + >2^d</em + > elements.</li + ></ul + ></div + ><div class="subs bundled-patterns" + ><p class="caption" + >Bundled Patterns</p + ><table + ><tr + ><td class="src" + ><span class="keyword" + >pattern</span + > <a id="v:LR" class="def" + >LR</a + > :: a -> <a href="#" + >RTree</a + > 0 a</td + ><td class="doc" + ><p + >Leaf of a perfect depth tree</p + ><pre class="screen" + ><code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >LR 1 +</code + ></strong + >1 +<code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >let x = LR 1 +</code + ></strong + ><code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >:t x +</code + ></strong + >x :: Num a => RTree 0 a +</pre + ><p + >Can be used as a pattern:</p + ><pre class="screen" + ><code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >let f (LR a) (LR b) = a + b +</code + ></strong + ><code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >:t f +</code + ></strong + >f :: Num a => RTree 0 a -> RTree 0 a -> a +<code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >f (LR 1) (LR 2) +</code + ></strong + >3 +</pre + ></td + ></tr + ><tr + ><td class="src" + ><span class="keyword" + >pattern</span + > <a id="v:BR" class="def" + >BR</a + > :: <a href="#" + >RTree</a + > d a -> <a href="#" + >RTree</a + > d a -> <a href="#" + >RTree</a + > (d <a href="#" + >+</a + > 1) a</td + ><td class="doc" + ><p + >Branch of a perfect depth tree</p + ><pre class="screen" + ><code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >BR (LR 1) (LR 2) +</code + ></strong + ><1,2> +<code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >let x = BR (LR 1) (LR 2) +</code + ></strong + ><code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >:t x +</code + ></strong + >x :: Num a => RTree 1 a +</pre + ><p + >Case be used a pattern:</p + ><pre class="screen" + ><code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >let f (BR (LR a) (LR b)) = LR (a + b) +</code + ></strong + ><code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >:t f +</code + ></strong + >f :: Num a => RTree 1 a -> RTree 0 a +<code class="prompt" + >>>> </code + ><strong class="userinput" + ><code + >f (BR (LR 1) (LR 2)) +</code + ></strong + >3 +</pre + ></td + ></tr + ></table + ></div + ></div + ></div + ></div + ><div id="footer" + ></div + ></body + ></html +>
\ No newline at end of file diff --git a/html-test/src/BundledPatterns.hs b/html-test/src/BundledPatterns.hs new file mode 100644 index 00000000..443e64fa --- /dev/null +++ b/html-test/src/BundledPatterns.hs @@ -0,0 +1,110 @@ +{-# LANGUAGE DataKinds, GADTs, KindSignatures, PatternSynonyms, TypeOperators, + ViewPatterns #-} +module BundledPatterns (Vec(Nil,(:>)), RTree (LR,BR)) where + +import GHC.TypeLits +import Prelude hiding (head, tail) +import Unsafe.Coerce + +-- | Fixed size vectors. +-- +-- * Lists with their length encoded in their type +-- * 'Vec'tor elements have an __ASCENDING__ subscript starting from 0 and +-- ending at @'length' - 1@. +data Vec :: Nat -> * -> * where + Nil :: Vec 0 a + Cons :: a -> Vec n a -> Vec (n + 1) a + +infixr 5 `Cons` + +-- | Add an element to the head of a vector. +-- +-- >>> 3:>4:>5:>Nil +-- <3,4,5> +-- >>> let x = 3:>4:>5:>Nil +-- >>> :t x +-- x :: Num a => Vec 3 a +-- +-- Can be used as a pattern: +-- +-- >>> let f (x :> y :> _) = x + y +-- >>> :t f +-- f :: Num a => Vec ((n + 1) + 1) a -> a +-- >>> f (3:>4:>5:>6:>7:>Nil) +-- 7 +-- +-- Also in conjunctions with (':<'): +-- +-- >>> let g (a :> b :> (_ :< y :< x)) = a + b + x + y +-- >>> :t g +-- g :: Num a => Vec ((((n + 1) + 1) + 1) + 1) a -> a +-- >>> g (1:>2:>3:>4:>5:>Nil) +-- 12 +pattern (:>) :: a -> Vec n a -> Vec (n + 1) a +pattern (:>) x xs <- ((\ys -> (head ys,tail ys)) -> (x,xs)) + where + (:>) x xs = Cons x xs + +infixr 5 :> + +head :: Vec (n + 1) a -> a +head (x `Cons` _) = x + +tail :: Vec (n + 1) a -> Vec n a +tail (_ `Cons` xs) = unsafeCoerce xs + +-- | Perfect depth binary tree. +-- +-- * Only has elements at the leaf of the tree +-- * A tree of depth /d/ has /2^d/ elements. +data RTree :: Nat -> * -> * where + LR_ :: a -> RTree 0 a + BR_ :: RTree d a -> RTree d a -> RTree (d+1) a + +textract :: RTree 0 a -> a +textract (LR_ x) = x +{-# NOINLINE textract #-} + +tsplit :: RTree (d+1) a -> (RTree d a,RTree d a) +tsplit (BR_ l r) = (unsafeCoerce l, unsafeCoerce r) +{-# NOINLINE tsplit #-} + +-- | Leaf of a perfect depth tree +-- +-- >>> LR 1 +-- 1 +-- >>> let x = LR 1 +-- >>> :t x +-- x :: Num a => RTree 0 a +-- +-- Can be used as a pattern: +-- +-- >>> let f (LR a) (LR b) = a + b +-- >>> :t f +-- f :: Num a => RTree 0 a -> RTree 0 a -> a +-- >>> f (LR 1) (LR 2) +-- 3 +pattern LR :: a -> RTree 0 a +pattern LR x <- (textract -> x) + where + LR x = LR_ x + +-- | Branch of a perfect depth tree +-- +-- >>> BR (LR 1) (LR 2) +-- <1,2> +-- >>> let x = BR (LR 1) (LR 2) +-- >>> :t x +-- x :: Num a => RTree 1 a +-- +-- Case be used a pattern: +-- +-- >>> let f (BR (LR a) (LR b)) = LR (a + b) +-- >>> :t f +-- f :: Num a => RTree 1 a -> RTree 0 a +-- >>> f (BR (LR 1) (LR 2)) +-- 3 +pattern BR :: RTree d a -> RTree d a -> RTree (d+1) a +pattern BR l r <- ((\t -> (tsplit t)) -> (l,r)) + where + BR l r = BR_ l r diff --git a/html-test/src/BundledPatterns2.hs b/html-test/src/BundledPatterns2.hs new file mode 100644 index 00000000..5e9a83a7 --- /dev/null +++ b/html-test/src/BundledPatterns2.hs @@ -0,0 +1,10 @@ +{-# LANGUAGE DataKinds, GADTs, KindSignatures, PatternSynonyms, TypeOperators, + ViewPatterns #-} +module BundledPatterns2 (Vec((:>), Empty), RTree(..)) where + +import GHC.TypeLits + +import BundledPatterns + +pattern Empty :: Vec 0 a +pattern Empty <- Nil |