[Git][ghc/ghc][wip/marge_bot_batch_merge_job] 4 commits: Improve Monad, Functor & Applicative docs
Marge Bot (@marge-bot)
gitlab at gitlab.haskell.org
Thu Feb 8 20:12:05 UTC 2024
Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
762b2120 by Jade at 2024-02-08T15:17:15+00:00
Improve Monad, Functor & Applicative docs
This patch aims to improve the documentation of Functor, Applicative,
Monad and related symbols. The main goal is to make it more consistent
and make accessible. See also: !10979 (closed) and !10985 (closed)
Ticket #17929
Updates haddock submodule
- - - - -
60c577c1 by Josh Meredith at 2024-02-08T15:11:40-05:00
JavaScript codegen: Use GHC's tag inference where JS backend-specific evaluation inference was previously used (#24309)
- - - - -
7581c522 by Zubin Duggal at 2024-02-08T15:11:42-05:00
ci: Allow release-hackage-lint to fail
Otherwise it blocks the ghcup metadata pipeline from running.
- - - - -
dba6140c by doyougnu at 2024-02-08T15:11:46-05:00
gitlab: js: add codeowners
Fixes:
- #24409
Follow on from:
- #21078 and MR !9133
- When we added the JS backend this was forgotten. This patch adds the
rightful codeowners.
- - - - -
20 changed files:
- .gitlab-ci.yml
- CODEOWNERS
- compiler/GHC/JS/JStg/Syntax.hs
- compiler/GHC/Stg/InferTags/Rewrite.hs
- compiler/GHC/StgToJS/Apply.hs
- compiler/GHC/StgToJS/Expr.hs
- compiler/GHC/StgToJS/ExprCtx.hs
- compiler/GHC/StgToJS/Types.hs
- compiler/GHC/StgToJS/Utils.hs
- libraries/base/src/Control/Applicative.hs
- libraries/base/src/Data/Functor/Compose.hs
- libraries/base/src/Data/Functor/Product.hs
- libraries/base/src/Data/Functor/Sum.hs
- libraries/ghc-internal/src/Control/Monad.hs
- libraries/ghc-internal/src/Data/Functor.hs
- libraries/ghc-internal/src/Data/Functor/Const.hs
- libraries/ghc-internal/src/Data/Functor/Identity.hs
- libraries/ghc-internal/src/GHC/Base.hs
- libraries/ghc-internal/src/GHC/Functor/ZipList.hs
- utils/haddock
Changes:
=====================================
.gitlab-ci.yml
=====================================
@@ -841,6 +841,10 @@ release-hackage-lint:
rules:
- if: '$RELEASE_JOB == "yes"'
extends: .hackage
+ # The ghcup metadata pipeline requires all prior jobs to
+ # pass. The hackage job can easily fail due to API changes
+ # or similar - so we allow it to fail.
+ allow_failure: true
variables:
# No slow-validate bindist on release pipeline
EXTRA_HC_OPTS: "-dlint"
=====================================
CODEOWNERS
=====================================
@@ -52,6 +52,8 @@
/compiler/GHC/Core/Opt/ @simonpj @sgraf
/compiler/GHC/ThToHs.hs @rae
/compiler/GHC/Wasm/ @nrnrnr
+/compiler/GHC/JS/ @luite @doyougnu @hsyl20 @JoshMeredith
+/compiler/GHC/StgToJS/ @luite @doyougnu @hsyl20 @JoshMeredith
[Core libraries]
/libraries/base/ @hvr
=====================================
compiler/GHC/JS/JStg/Syntax.hs
=====================================
@@ -70,6 +70,7 @@ module GHC.JS.JStg.Syntax
) where
import GHC.Prelude
+import GHC.Utils.Outputable
import GHC.JS.Ident
@@ -148,6 +149,16 @@ data JStgExpr
| ApplExpr JStgExpr [JStgExpr] -- ^ Application
deriving (Eq, Typeable, Generic)
+instance Outputable JStgExpr where
+ ppr x = case x of
+ ValExpr _ -> text ("ValExpr" :: String)
+ SelExpr x' _ -> text ("SelExpr" :: String) <+> ppr x'
+ IdxExpr x' y' -> text ("IdxExpr" :: String) <+> ppr (x', y')
+ InfixExpr _ x' y' -> text ("InfixExpr" :: String) <+> ppr (x', y')
+ UOpExpr _ x' -> text ("UOpExpr" :: String) <+> ppr x'
+ IfExpr p t e -> text ("IfExpr" :: String) <+> ppr (p, t, e)
+ ApplExpr x' xs -> text ("ApplExpr" :: String) <+> ppr (x', xs)
+
-- * Useful pattern synonyms to ease programming with the deeply embedded JS
-- AST. Each pattern wraps @UOp@ and @Op@ into a @JStgExpr at s to save typing and
-- for convienience. In addition we include a string wrapper for JS string
=====================================
compiler/GHC/Stg/InferTags/Rewrite.hs
=====================================
@@ -7,7 +7,7 @@
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeFamilies #-}
-module GHC.Stg.InferTags.Rewrite (rewriteTopBinds)
+module GHC.Stg.InferTags.Rewrite (rewriteTopBinds, rewriteOpApp)
where
import GHC.Prelude
@@ -388,15 +388,15 @@ rewriteId v = do
if is_tagged then return $! setIdTagSig v (TagSig TagProper)
else return v
-rewriteExpr :: InferStgExpr -> RM TgStgExpr
-rewriteExpr (e at StgCase {}) = rewriteCase e
-rewriteExpr (e at StgLet {}) = rewriteLet e
-rewriteExpr (e at StgLetNoEscape {}) = rewriteLetNoEscape e
-rewriteExpr (StgTick t e) = StgTick t <$!> rewriteExpr e
-rewriteExpr e@(StgConApp {}) = rewriteConApp e
-rewriteExpr e@(StgOpApp {}) = rewriteOpApp e
-rewriteExpr e@(StgApp {}) = rewriteApp e
-rewriteExpr (StgLit lit) = return $! (StgLit lit)
+rewriteExpr :: GenStgExpr 'InferTaggedBinders -> RM (GenStgExpr 'CodeGen)
+rewriteExpr (e at StgCase {}) = rewriteCase e
+rewriteExpr (e at StgLet {}) = rewriteLet e
+rewriteExpr (e at StgLetNoEscape {}) = rewriteLetNoEscape e
+rewriteExpr (StgTick t e) = StgTick t <$!> rewriteExpr e
+rewriteExpr e@(StgConApp {}) = rewriteConApp e
+rewriteExpr e@(StgApp {}) = rewriteApp e
+rewriteExpr (StgLit lit) = return $! (StgLit lit)
+rewriteExpr (StgOpApp op args res_ty) = (StgOpApp op) <$!> rewriteArgs args <*> pure res_ty
rewriteCase :: InferStgExpr -> RM TgStgExpr
@@ -404,7 +404,7 @@ rewriteCase (StgCase scrut bndr alt_type alts) =
withBinder NotTopLevel bndr $
pure StgCase <*>
rewriteExpr scrut <*>
- pure (fst bndr) <*>
+ rewriteId (fst bndr) <*>
pure alt_type <*>
mapM rewriteAlt alts
=====================================
compiler/GHC/StgToJS/Apply.hs
=====================================
@@ -157,7 +157,7 @@ genApp ctx i args
| [] <- args
, [vt] <- idJSRep i
, isUnboxable vt
- , ctxIsEvaluated ctx i
+ , ctxIsEvaluated i
= do
let c = head (concatMap typex_expr $ ctxTarget ctx)
is <- varsForId i
@@ -171,7 +171,7 @@ genApp ctx i args
-- case of Id without args and known to be already evaluated: return fields
-- individually
| [] <- args
- , ctxIsEvaluated ctx i || isStrictType (idType i)
+ , ctxIsEvaluated i || isStrictType (idType i)
= do
a <- storeIdFields i (ctxTarget ctx)
-- optional runtime assert for detecting unexpected thunks (unevaluated)
@@ -199,7 +199,7 @@ genApp ctx i args
a' = case args of
[StgVarArg a'] -> a'
_ -> panic "genApp: unexpected arg"
- if isStrictId a' || ctxIsEvaluated ctx a'
+ if isStrictId a' || ctxIsEvaluated a'
then return (t |= ai, ExprInline Nothing)
else return (returnS (app "h$e" [ai]), ExprCont)
_ -> panic "genApp: invalid size"
=====================================
compiler/GHC/StgToJS/Expr.hs
=====================================
@@ -137,12 +137,12 @@ genBind ctx bndr =
j <- assign b r >>= \case
Just ja -> return ja
Nothing -> allocCls Nothing [(b,r)]
- return (j, addEvalRhs ctx [(b,r)])
+ return (j, ctx)
StgRec bs -> do
jas <- mapM (uncurry assign) bs -- fixme these might depend on parts initialized by allocCls
let m = if null jas then Nothing else Just (mconcat $ catMaybes jas)
j <- allocCls m . map snd . filter (isNothing . fst) $ zip jas bs
- return (j, addEvalRhs ctx bs)
+ return (j, ctx)
where
ctx' = ctxClearLneFrame ctx
@@ -168,7 +168,7 @@ genBind ctx bndr =
(tgt ||= ApplExpr (var ("h$c_sel_" <> mkFastString sel_tag)) [the_fvj])
_ -> panic "genBind.assign: invalid size"
assign b (StgRhsClosure _ext _ccs _upd [] expr _typ)
- | snd (isInlineExpr (ctxEvaluatedIds ctx) expr) = do
+ | isInlineExpr expr = do
d <- declVarsForId b
tgt <- varsForId b
let ctx' = ctx { ctxTarget = assocIdExprs b tgt }
@@ -177,12 +177,6 @@ genBind ctx bndr =
assign _b StgRhsCon{} = return Nothing
assign b r = genEntry ctx' b r >> return Nothing
- addEvalRhs c [] = c
- addEvalRhs c ((b,r):xs)
- | StgRhsCon{} <- r = addEvalRhs (ctxAssertEvaluated b c) xs
- | (StgRhsClosure _ _ ReEntrant _ _ _) <- r = addEvalRhs (ctxAssertEvaluated b c) xs
- | otherwise = addEvalRhs c xs
-
genBindLne :: HasDebugCallStack
=> ExprCtx
-> CgStgBinding
@@ -559,7 +553,7 @@ genCase :: HasDebugCallStack
-> LiveVars
-> G (JStgStat, ExprResult)
genCase ctx bnd e at alts l
- | snd (isInlineExpr (ctxEvaluatedIds ctx) e) = do
+ | isInlineExpr e = do
bndi <- identsForId bnd
let ctx' = ctxSetTop bnd
$ ctxSetTarget (assocIdExprs bnd (map toJExpr bndi))
@@ -570,7 +564,7 @@ genCase ctx bnd e at alts l
ExprCont -> pprPanic "genCase: expression was not inline"
(pprStgExpr panicStgPprOpts e)
- (aj, ar) <- genAlts (ctxAssertEvaluated bnd ctx) bnd at d alts
+ (aj, ar) <- genAlts ctx bnd at d alts
(saveCCS,restoreCCS) <- ifProfilingM $ do
ccsVar <- freshIdent
pure ( ccsVar ||= toJExpr jCurrentCCS
@@ -586,7 +580,7 @@ genCase ctx bnd e at alts l
, ar
)
| otherwise = do
- rj <- genRet (ctxAssertEvaluated bnd ctx) bnd at alts l
+ rj <- genRet ctx bnd at alts l
let ctx' = ctxSetTop bnd
$ ctxSetTarget (assocIdExprs bnd (map toJExpr [R1 ..]))
$ ctx
=====================================
compiler/GHC/StgToJS/ExprCtx.hs
=====================================
@@ -18,14 +18,12 @@
module GHC.StgToJS.ExprCtx
( ExprCtx
, initExprCtx
- , ctxAssertEvaluated
, ctxIsEvaluated
, ctxSetSrcSpan
, ctxSrcSpan
, ctxSetTop
, ctxTarget
, ctxSetTarget
- , ctxEvaluatedIds
-- * Let-no-escape
, ctxClearLneFrame
, ctxUpdateLneFrame
@@ -43,9 +41,12 @@ import GHC.Prelude
import GHC.StgToJS.Types
import GHC.Types.Unique.FM
-import GHC.Types.Unique.Set
import GHC.Types.Var
import GHC.Types.SrcLoc
+import GHC.Types.Id
+import GHC.Types.Id.Info
+
+import GHC.Stg.InferTags.TagSig
import GHC.Utils.Outputable
import GHC.Utils.Panic
@@ -61,10 +62,6 @@ data ExprCtx = ExprCtx
, ctxTarget :: [TypedExpr]
-- ^ Target variables for the evaluated expression
- , ctxEvaluatedIds :: UniqSet Id
- -- ^ Ids that we know to be evaluated (e.g. case binders when the expression
- -- to evaluate is in an alternative)
-
, ctxSrcSpan :: Maybe RealSrcSpan
-- ^ Source location
@@ -95,7 +92,6 @@ initExprCtx :: Id -> ExprCtx
initExprCtx i = ExprCtx
{ ctxTop = i
, ctxTarget = []
- , ctxEvaluatedIds = emptyUniqSet
, ctxLneFrameBs = emptyUFM
, ctxLneFrameVars = []
, ctxLneFrameSize = 0
@@ -110,10 +106,6 @@ ctxSetTarget t ctx = ctx { ctxTarget = t }
ctxSetTop :: Id -> ExprCtx -> ExprCtx
ctxSetTop i ctx = ctx { ctxTop = i }
--- | Add an Id to the known-evaluated set
-ctxAssertEvaluated :: Id -> ExprCtx -> ExprCtx
-ctxAssertEvaluated i ctx = ctx { ctxEvaluatedIds = addOneToUniqSet (ctxEvaluatedIds ctx) i }
-
-- | Set source location
ctxSetSrcSpan :: RealSrcSpan -> ExprCtx -> ExprCtx
ctxSetSrcSpan span ctx = ctx { ctxSrcSpan = Just span }
@@ -139,8 +131,39 @@ ctxClearLneFrame ctx =
}
-- | Predicate: do we know for sure that the given Id is evaluated?
-ctxIsEvaluated :: ExprCtx -> Id -> Bool
-ctxIsEvaluated ctx i = i `elementOfUniqSet` ctxEvaluatedIds ctx
+ctxIsEvaluated :: Id -> Bool
+ctxIsEvaluated i =
+ maybe False isTaggedSig (idTagSig_maybe i)
+ && go (idDetails i)
+ where
+ go JoinId{} = False
+ go _ = True
+
+
+ -- DFunId new_type -> not new_type
+ -- -- DFuns terminate, unless the dict is implemented
+ -- -- with a newtype in which case they may not
+
+ -- DataConWorkId {} -> True
+
+ -- ClassOpId {} -> False
+ -- -- suppose an argument, and we don't have one
+
+ -- PrimOpId op _ -> primop_ok op
+ -- -- probably already handled by StgOpApp
+
+ -- JoinId {} -> False
+ -- -- Don't speculate join points
+
+ -- TickBoxOpId {} -> False
+ -- -- Don't speculate box ticking
+
+ -- -- Tagged (evaluated) ids
+ -- _ | Just sig <- idTagSig_maybe i
+ -- , isTaggedSig sig
+ -- -> True
+
+ -- _ -> False
-- | Does the given Id correspond to a LNE binding
ctxIsLneBinding :: ExprCtx -> Id -> Bool
=====================================
compiler/GHC/StgToJS/Types.hs
=====================================
@@ -342,6 +342,9 @@ data TypedExpr = TypedExpr
, typex_expr :: [JStgExpr]
}
+instance Outputable TypedExpr where
+ ppr (TypedExpr typ x) = ppr (typ, x)
+
-- | A Primop result is either an inlining of some JS payload, or a primitive
-- call to a JS function defined in Shim files in base.
data PrimRes
=====================================
compiler/GHC/StgToJS/Utils.hs
=====================================
@@ -69,7 +69,6 @@ import GHC.Types.Var.Set
import GHC.Types.Id
import GHC.Types.Id.Info
import GHC.Types.Unique.FM
-import GHC.Types.Unique.Set
import GHC.Types.ForeignCall
import GHC.Types.TyThing
import GHC.Types.Name
@@ -108,11 +107,16 @@ assignToExprCtx ctx es = assignToTypedExprs (ctxTarget ctx) es
assignCoerce1 :: [TypedExpr] -> [TypedExpr] -> JStgStat
assignCoerce1 [x] [y] = assignCoerce x y
assignCoerce1 [] [] = mempty
-assignCoerce1 _x _y = pprPanic "assignCoerce1"
+-- We silently ignore the case of an empty list on the first argument. It denotes
+-- "assign nothing to n empty slots on the right". Usually this case shouldn't come
+-- up, but rare cases where the earlier code can't correctly guess the size of type
+-- classes causes slots to be allocated when they aren't needed.
+assignCoerce1 [] _ = mempty
+assignCoerce1 x y = pprPanic "assignCoerce1"
(vcat [ text "lengths do not match"
-- FIXME: Outputable instance removed until JStg replaces JStat
- -- , ppr x
- -- , ppr y
+ , ppr x
+ , ppr y
])
-- | Assign p2 to p1 with optional coercion
@@ -417,61 +421,48 @@ stgLneLiveExpr rhs = dVarSetElems (liveVars $ stgRhsLive rhs)
-- stgLneLiveExpr StgRhsCon {} = []
-- | returns True if the expression is definitely inline
-isInlineExpr :: UniqSet Id -> CgStgExpr -> (UniqSet Id, Bool)
-isInlineExpr v = \case
+isInlineExpr :: CgStgExpr -> Bool
+isInlineExpr = \case
StgApp i args
- -> (emptyUniqSet, isInlineApp v i args)
+ -> isInlineApp i args
StgLit{}
- -> (emptyUniqSet, True)
+ -> True
StgConApp{}
- -> (emptyUniqSet, True)
+ -> True
StgOpApp (StgFCallOp f _) _ _
- -> (emptyUniqSet, isInlineForeignCall f)
+ -> isInlineForeignCall f
StgOpApp (StgPrimOp SeqOp) [StgVarArg e] t
- -> (emptyUniqSet, e `elementOfUniqSet` v || isStrictType t)
+ -> ctxIsEvaluated e || isStrictType t
StgOpApp (StgPrimOp op) _ _
- -> (emptyUniqSet, primOpIsReallyInline op)
+ -> primOpIsReallyInline op
StgOpApp (StgPrimCallOp _c) _ _
- -> (emptyUniqSet, True)
- StgCase e b _ alts
- ->let (_ve, ie) = isInlineExpr v e
- v' = addOneToUniqSet v b
- (vas, ias) = unzip $ map (isInlineExpr v') (fmap alt_rhs alts)
- vr = L.foldl1' intersectUniqSets vas
- in (vr, (ie || b `elementOfUniqSet` v) && and ias)
- StgLet _ b e
- -> isInlineExpr (inspectInlineBinding v b) e
- StgLetNoEscape _ _b e
- -> isInlineExpr v e
- StgTick _ e
- -> isInlineExpr v e
-
-inspectInlineBinding :: UniqSet Id -> CgStgBinding -> UniqSet Id
-inspectInlineBinding v = \case
- StgNonRec i r -> inspectInlineRhs v i r
- StgRec bs -> foldl' (\v' (i,r) -> inspectInlineRhs v' i r) v bs
-
-inspectInlineRhs :: UniqSet Id -> Id -> CgStgRhs -> UniqSet Id
-inspectInlineRhs v i = \case
- StgRhsCon{} -> addOneToUniqSet v i
- StgRhsClosure _ _ ReEntrant _ _ _ -> addOneToUniqSet v i
- _ -> v
+ -> True
+ StgCase e _ _ alts
+ ->let ie = isInlineExpr e
+ ias = map isInlineExpr (fmap alt_rhs alts)
+ in ie && and ias
+ StgLet _ _ e
+ -> isInlineExpr e
+ StgLetNoEscape _ _ e
+ -> isInlineExpr e
+ StgTick _ e
+ -> isInlineExpr e
isInlineForeignCall :: ForeignCall -> Bool
isInlineForeignCall (CCall (CCallSpec _ cconv safety)) =
not (playInterruptible safety) &&
not (cconv /= JavaScriptCallConv && playSafe safety)
-isInlineApp :: UniqSet Id -> Id -> [StgArg] -> Bool
-isInlineApp v i = \case
+isInlineApp :: Id -> [StgArg] -> Bool
+isInlineApp i = \case
_ | isJoinId i -> False
[] -> isUnboxedTupleType (idType i) ||
isStrictType (idType i) ||
- i `elementOfUniqSet` v
+ ctxIsEvaluated i
[StgVarArg a]
| DataConWrapId dc <- idDetails i
, isNewTyCon (dataConTyCon dc)
- , isStrictType (idType a) || a `elementOfUniqSet` v || isStrictId a
+ , isStrictType (idType a) || ctxIsEvaluated a || isStrictId a
-> True
_ -> False
=====================================
libraries/base/src/Control/Applicative.hs
=====================================
@@ -137,6 +137,7 @@ deriving instance (Typeable (a :: Type -> Type -> Type), Typeable b, Typeable c,
--
-- >>> runExcept $ canFail *> final
-- Left "it failed"
+--
-- >>> runExcept $ optional canFail *> final
-- Right 42
=====================================
libraries/base/src/Data/Functor/Compose.hs
=====================================
@@ -42,6 +42,17 @@ infixr 9 `Compose`
-- | Right-to-left composition of functors.
-- The composition of applicative functors is always applicative,
-- but the composition of monads is not always a monad.
+--
+-- ==== __Examples__
+--
+-- >>> fmap (subtract 1) (Compose (Just [1, 2, 3]))
+-- Compose (Just [0,1,2])
+--
+-- >>> Compose (Just [1, 2, 3]) <> Compose Nothing
+-- Compose (Just [1,2,3])
+--
+-- >>> Compose (Just [(++ "World"), (++ "Haskell")]) <*> Compose (Just ["Hello, "])
+-- Compose (Just ["Hello, World","Hello, Haskell"])
newtype Compose f g a = Compose { getCompose :: f (g a) }
deriving ( Data -- ^ @since 4.9.0.0
, Generic -- ^ @since 4.9.0.0
=====================================
libraries/base/src/Data/Functor/Product.hs
=====================================
@@ -32,6 +32,14 @@ import GHC.Generics (Generic, Generic1)
import Text.Read ()
-- | Lifted product of functors.
+--
+-- ==== __Examples__
+--
+-- >>> fmap (+1) (Pair [1, 2, 3] (Just 0))
+-- Pair [2,3,4] (Just 1)
+--
+-- >>> Pair "Hello, " (Left 'x') <> Pair "World" (Right 'y')
+-- Pair "Hello, World" (Right 'y')
data Product f g a = Pair (f a) (g a)
deriving ( Data -- ^ @since 4.9.0.0
, Generic -- ^ @since 4.9.0.0
=====================================
libraries/base/src/Data/Functor/Sum.hs
=====================================
@@ -29,6 +29,14 @@ import GHC.Generics (Generic, Generic1)
import Text.Read ()
-- | Lifted sum of functors.
+--
+-- ==== __Examples__
+--
+-- >>> fmap (+1) (InL (Just 1)) :: Sum Maybe [] Int
+-- InL (Just 2)
+--
+-- >>> fmap (+1) (InR [1, 2, 3]) :: Sum Maybe [] Int
+-- InR [2,3,4]
data Sum f g a = InL (f a) | InR (g a)
deriving ( Data -- ^ @since 4.9.0.0
, Generic -- ^ @since 4.9.0.0
=====================================
libraries/ghc-internal/src/Control/Monad.hs
=====================================
@@ -137,14 +137,40 @@ guard True = pure ()
guard False = empty
-- | This generalizes the list-based 'Data.List.filter' function.
-
+--
+-- > runIdentity (filterM (Identity . p) xs) == filter p xs
+--
+-- ==== __Examples__
+--
+-- >>> filterM (\x -> do
+-- putStrLn ("Keep: " ++ show x ++ "?")
+-- answer <- getLine
+-- pure (answer == "y"))
+-- [1, 2, 3]
+-- Keep: 1?
+-- y
+-- Keep: 2?
+-- n
+-- Keep: 3?
+-- y
+-- [1,3]
+--
+-- >>> filterM (\x -> do
+-- putStr (show x)
+-- x' <- readLn
+-- pure (x == x'))
+-- [1, 2, 3]
+-- 12
+-- 22
+-- 33
+-- [2,3]
{-# INLINE filterM #-}
filterM :: (Applicative m) => (a -> m Bool) -> [a] -> m [a]
filterM p = foldr (\ x -> liftA2 (\ flg -> if flg then (x:) else id) (p x)) (pure [])
infixr 1 <=<, >=>
--- | Left-to-right composition of Kleisli arrows.
+-- | Left-to-right composition of 'Control.Arrow.Kleisli' arrows.
--
-- \'@(bs '>=>' cs) a@\' can be understood as the @do@ expression
--
@@ -152,6 +178,10 @@ infixr 1 <=<, >=>
-- do b <- bs a
-- cs b
-- @
+--
+-- or in terms of @'(>>=)'@ as
+--
+-- > bs a >>= cs
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c)
f >=> g = \x -> f x >>= g
@@ -280,10 +310,18 @@ Core: https://gitlab.haskell.org/ghc/ghc/issues/11795#note_118976
-}
-- | @'replicateM' n act@ performs the action @act@ @n@ times,
--- and then returns the list of results:
+-- and then returns the list of results.
+--
+-- @replicateM n (pure x) == 'replicate' n x@
--
-- ==== __Examples__
--
+-- >>> replicateM 3 getLine
+-- hi
+-- heya
+-- hiya
+-- ["hi","heya","hiya"]
+--
-- >>> import Control.Monad.State
-- >>> runState (replicateM 3 $ state $ \s -> (s, s + 1)) 1
-- ([1,2,3],4)
@@ -303,11 +341,8 @@ replicateM cnt0 f =
--
-- ==== __Examples__
--
--- >>> replicateM_ 3 (putStrLn "a")
--- a
--- a
--- a
---
+-- >>> replicateM_ 3 (putStr "a")
+-- aaa
replicateM_ :: (Applicative m) => Int -> m a -> m ()
{-# INLINABLE replicateM_ #-}
{-# SPECIALISE replicateM_ :: Int -> IO a -> IO () #-}
@@ -321,6 +356,16 @@ replicateM_ cnt0 f =
-- | The reverse of 'when'.
+--
+-- ==== __Examples__
+--
+-- >>> do x <- getLine
+-- unless (x == "hi") (putStrLn "hi!")
+-- comingupwithexamplesisdifficult
+-- hi!
+--
+-- >>> unless (pi > exp 1) Nothing
+-- Just ()
unless :: (Applicative f) => Bool -> f () -> f ()
{-# INLINABLE unless #-}
{-# SPECIALISE unless :: Bool -> IO () -> IO () #-}
=====================================
libraries/ghc-internal/src/Data/Functor.hs
=====================================
@@ -34,6 +34,7 @@
--
-- >>> fmap show (Just 1) -- (Int -> String) -> Maybe Int -> Maybe String
-- Just "1"
+--
-- >>> show <$> (Just 1) -- (Int -> String) -> Maybe Int -> Maybe String
-- Just "1"
@@ -74,6 +75,7 @@ infixl 4 <$>
--
-- >>> show <$> Nothing
-- Nothing
+--
-- >>> show <$> Just 3
-- Just "3"
--
@@ -82,6 +84,7 @@ infixl 4 <$>
--
-- >>> show <$> Left 17
-- Left 17
+--
-- >>> show <$> Right 17
-- Right "17"
--
@@ -136,6 +139,7 @@ infixl 4 $>
--
-- >>> Nothing $> "foo"
-- Nothing
+--
-- >>> Just 90210 $> "foo"
-- Just "foo"
--
@@ -145,6 +149,7 @@ infixl 4 $>
--
-- >>> Left 8675309 $> "foo"
-- Left 8675309
+--
-- >>> Right 8675309 $> "foo"
-- Right "foo"
--
@@ -163,6 +168,14 @@ infixl 4 $>
-- | Generalization of @Data.List.@'Data.List.unzip'.
--
+-- ==== __Examples__
+--
+-- >>> unzip (Just ("Hello", "World"))
+-- (Just "Hello",Just "World")
+--
+-- >>> unzip [("I", "love"), ("really", "haskell")]
+-- (["I","really"],["love","haskell"])
+--
-- @since 4.19.0.0
unzip :: Functor f => f (a, b) -> (f a, f b)
unzip xs = (fst <$> xs, snd <$> xs)
@@ -176,6 +189,7 @@ unzip xs = (fst <$> xs, snd <$> xs)
--
-- >>> void Nothing
-- Nothing
+--
-- >>> void (Just 3)
-- Just ()
--
@@ -184,6 +198,7 @@ unzip xs = (fst <$> xs, snd <$> xs)
--
-- >>> void (Left 8675309)
-- Left 8675309
+--
-- >>> void (Right 8675309)
-- Right ()
--
@@ -203,6 +218,7 @@ unzip xs = (fst <$> xs, snd <$> xs)
-- 1
-- 2
-- [(),()]
+--
-- >>> void $ mapM print [1,2]
-- 1
-- 2
=====================================
libraries/ghc-internal/src/Data/Functor/Const.hs
=====================================
@@ -36,6 +36,19 @@ import GHC.Read (Read(readsPrec), readParen, lex)
import GHC.Show (Show(showsPrec), showParen, showString)
-- | The 'Const' functor.
+--
+-- ==== __Examples__
+--
+-- >>> fmap (++ "World") (Const "Hello")
+-- Const "Hello"
+--
+-- Because we ignore the second type parameter to 'Const',
+-- the Applicative instance, which has
+-- @'(<*>)' :: Monoid m => Const m (a -> b) -> Const m a -> Const m b@
+-- essentially turns into @Monoid m => m -> m -> m@, which is '(<>)'
+--
+-- >>> Const [1, 2, 3] <*> Const [4, 5, 6]
+-- Const [1,2,3,4,5,6]
newtype Const a b = Const { getConst :: a }
deriving ( Bits -- ^ @since 4.9.0.0
, Bounded -- ^ @since 4.9.0.0
=====================================
libraries/ghc-internal/src/Data/Functor/Identity.hs
=====================================
@@ -53,6 +53,22 @@ import GHC.Types (Bool(..))
-- | Identity functor and monad. (a non-strict monad)
--
+-- ==== __Examples__
+--
+-- >>> fmap (+1) (Identity 0)
+-- Identity 1
+--
+-- >>> Identity [1, 2, 3] <> Identity [4, 5, 6]
+-- Identity [1,2,3,4,5,6]
+--
+-- @
+-- >>> do
+-- x <- Identity 10
+-- y <- Identity (x + 5)
+-- pure (x + y)
+-- Identity 25
+-- @
+--
-- @since 4.8.0.0
newtype Identity a = Identity { runIdentity :: a }
deriving ( Bits -- ^ @since 4.9.0.0
=====================================
libraries/ghc-internal/src/GHC/Base.hs
=====================================
@@ -679,8 +679,8 @@ structure of @f at . Furthermore @f@ needs to adhere to the following:
Note, that the second law follows from the free theorem of the type 'fmap' and
the first law, so you need only check that the former condition holds.
-See <https://www.schoolofhaskell.com/user/edwardk/snippets/fmap> or
-<https://github.com/quchen/articles/blob/master/second_functor_law.md>
+See these articles by <https://www.schoolofhaskell.com/user/edwardk/snippets/fmap School of Haskell> or
+<https://github.com/quchen/articles/blob/master/second_functor_law.md David Luposchainsky>
for an explanation.
-}
@@ -818,7 +818,18 @@ class Functor f where
class Functor f => Applicative f where
{-# MINIMAL pure, ((<*>) | liftA2) #-}
- -- | Lift a value.
+ -- | Lift a value into the Structure.
+ --
+ -- ==== __Examples__
+ --
+ -- >>> pure 1 :: Maybe Int
+ -- Just 1
+ --
+ -- >>> pure 'z' :: [Char]
+ -- "z"
+ --
+ -- >>> pure (pure ":D") :: Maybe [String]
+ -- Just [":D"]
pure :: a -> f a
-- | Sequential application.
@@ -827,12 +838,11 @@ class Functor f => Applicative f where
-- efficient than the default one.
--
-- ==== __Example__
- -- Used in combination with @('<$>')@, @('<*>')@ can be used to build a record.
+ -- Used in combination with @'(Data.Functor.<$>)'@, @'(<*>)'@ can be used to build a record.
--
-- >>> data MyState = MyState {arg1 :: Foo, arg2 :: Bar, arg3 :: Baz}
--
-- >>> produceFoo :: Applicative f => f Foo
- --
-- >>> produceBar :: Applicative f => f Bar
-- >>> produceBaz :: Applicative f => f Baz
--
@@ -852,9 +862,12 @@ class Functor f => Applicative f where
-- a function defined in terms of '<*>' and 'fmap'.
--
-- ==== __Example__
+ --
-- >>> liftA2 (,) (Just 3) (Just 5)
-- Just (3,5)
-
+ --
+ -- >>> liftA2 (+) [1, 2, 3] [4, 5, 6]
+ -- [5,6,7,6,7,8,7,8,9]
liftA2 :: (a -> b -> c) -> f a -> f b -> f c
liftA2 f x = (<*>) (fmap f x)
@@ -909,6 +922,9 @@ class Functor f => Applicative f where
-- >>> flip (<*>) (print 1) (id <$ print 2)
-- 2
-- 1
+--
+-- >>> ZipList [4, 5, 6] <**> ZipList [(+1), (*2), (/3)]
+-- ZipList {getZipList = [5.0,10.0,2.0]}
(<**>) :: Applicative f => f a -> f (a -> b) -> f b
(<**>) = liftA2 (\a f -> f a)
@@ -963,6 +979,12 @@ liftA3 f a b c = liftA2 f a b <*> c
--
-- ==== __Examples__
--
+-- >>> join [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
+-- [1,2,3,4,5,6,7,8,9]
+--
+-- >>> join (Just (Just 3))
+-- Just 3
+--
-- A common use of 'join' is to run an 'IO' computation returned from
-- an 'GHC.Conc.STM' transaction, since 'GHC.Conc.STM' transactions
-- can't perform 'IO' directly. Recall that
@@ -1015,7 +1037,7 @@ The above laws imply:
and that 'pure' and ('<*>') satisfy the applicative functor laws.
-The instances of 'Monad' for lists, 'Data.Maybe.Maybe' and 'System.IO.IO'
+The instances of 'Monad' for 'GHC.List.List', 'Data.Maybe.Maybe' and 'System.IO.IO'
defined in the "Prelude" satisfy these laws.
-}
class Applicative m => Monad m where
@@ -1028,6 +1050,15 @@ class Applicative m => Monad m where
-- do a <- as
-- bs a
-- @
+ --
+ -- An alternative name for this function is \'bind\', but some people
+ -- may refer to it as \'flatMap\', which results from it being equivialent
+ -- to
+ --
+ -- @\\x f -> 'join' ('fmap' f x) :: Monad m => m a -> (a -> m b) -> m b@
+ --
+ -- which can be seen as mapping a value with
+ -- @Monad m => m a -> m (m b)@ and then \'flattening\' @m (m b)@ to @m b@ using 'join'.
(>>=) :: forall a b. m a -> (a -> m b) -> m b
-- | Sequentially compose two actions, discarding any value produced
@@ -1040,11 +1071,18 @@ class Applicative m => Monad m where
-- do as
-- bs
-- @
+ --
+ -- or in terms of @'(>>=)'@ as
+ --
+ -- > as >>= const bs
(>>) :: forall a b. m a -> m b -> m b
m >> k = m >>= \_ -> k -- See Note [Recursive bindings for Applicative/Monad]
{-# INLINE (>>) #-}
-- | Inject a value into the monadic type.
+ -- This function should /not/ be different from its default implementation
+ -- as 'pure'. The justification for the existence of this function is
+ -- merely historic.
return :: a -> m a
return = pure
@@ -1071,16 +1109,23 @@ original default.
-}
-- | Same as '>>=', but with the arguments interchanged.
+--
+-- > as >>= f == f =<< as
{-# SPECIALISE (=<<) :: (a -> [b]) -> [a] -> [b] #-}
(=<<) :: Monad m => (a -> m b) -> m a -> m b
f =<< x = x >>= f
-- | Conditional execution of 'Applicative' expressions. For example,
--
+-- ==== __Examples__
+--
-- > when debug (putStrLn "Debugging")
--
-- will output the string @Debugging@ if the Boolean value @debug@
-- is 'True', and otherwise do nothing.
+--
+-- >>> putStr "pi:" >> when False (print 3.14159)
+-- pi:
when :: (Applicative f) => Bool -> f () -> f ()
{-# INLINABLE when #-}
{-# SPECIALISE when :: Bool -> IO () -> IO () #-}
@@ -1119,15 +1164,23 @@ similar problems in nofib.
-}
-- | Promote a function to a monad.
+-- This is equivalent to 'fmap' but specialised to Monads.
liftM :: (Monad m) => (a1 -> r) -> m a1 -> m r
liftM f m1 = do { x1 <- m1; return (f x1) }
-- | Promote a function to a monad, scanning the monadic arguments from
--- left to right. For example,
+-- left to right.
+--
+-- ==== __Examples__
+--
+-- >>> liftM2 (+) [0,1] [0,2]
+-- [0,2,1,3]
--
--- > liftM2 (+) [0,1] [0,2] = [0,2,1,3]
--- > liftM2 (+) (Just 1) Nothing = Nothing
+-- >>> liftM2 (+) (Just 1) Nothing
+-- Nothing
--
+-- >>> liftM2 (+) (+ 3) (* 2) 5
+-- 18
liftM2 :: (Monad m) => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 f m1 m2 = do { x1 <- m1; x2 <- m2; return (f x1 x2) }
-- Caution: since this may be used for `liftA2`, we can't use the obvious
@@ -1171,10 +1224,13 @@ liftM5 f m1 m2 m3 m4 m5 = do { x1 <- m1; x2 <- m2; x3 <- m3; x4 <- m4; x5 <- m5;
is equivalent to
-> liftMn f x1 x2 ... xn
+> liftM<n> f x1 x2 ... xn
--}
+==== __Examples__
+>>> pure (\x y z -> x + y * z) `ap` Just 1 `ap` Just 5 `ap` Just 10
+Just 51
+-}
ap :: (Monad m) => m (a -> b) -> m a -> m b
ap m1 m2 = do { x1 <- m1; x2 <- m2; return (x1 x2) }
-- Since many Applicative instances define (<*>) = ap, we
@@ -1250,13 +1306,42 @@ infixl 3 <|>
-- * @'some' v = (:) 'Prelude.<$>' v '<*>' 'many' v@
--
-- * @'many' v = 'some' v '<|>' 'pure' []@
+--
+-- ==== __Examples__
+--
+-- >>> Nothing <|> Just 42
+-- Just 42
+--
+-- >>> [1, 2] <|> [3, 4]
+-- [1,2,3,4]
+--
+-- >>> empty <|> print (2^15)
+-- 32768
class Applicative f => Alternative f where
-- | The identity of '<|>'
+ --
+ -- > empty <|> a == a
+ -- > a <|> empty == a
empty :: f a
-- | An associative binary operation
(<|>) :: f a -> f a -> f a
-- | One or more.
+ --
+ -- ==== __Examples__
+ --
+ -- >>> some (putStr "la")
+ -- lalalalalalalalala... * goes on forever *
+ --
+ -- >>> some Nothing
+ -- nothing
+ --
+ -- >>> take 5 <$> some (Just 1)
+ -- * hangs forever *
+ --
+ -- Note that this function can be used with Parsers based on
+ -- Applicatives. In that case @some parser@ will attempt to
+ -- parse @parser@ one or more times until it fails.
some :: f a -> f [a]
some v = some_v
where
@@ -1264,6 +1349,21 @@ class Applicative f => Alternative f where
some_v = liftA2 (:) v many_v
-- | Zero or more.
+ --
+ -- ==== __Examples__
+ --
+ -- >>> many (putStr "la")
+ -- lalalalalalalalala... * goes on forever *
+ --
+ -- >>> many Nothing
+ -- Just []
+ --
+ -- >>> take 5 <$> many (Just 1)
+ -- * hangs forever *
+ --
+ -- Note that this function can be used with Parsers based on
+ -- Applicatives. In that case @many parser@ will attempt to
+ -- parse @parser@ zero or more times until it fails.
many :: f a -> f [a]
many v = many_v
where
=====================================
libraries/ghc-internal/src/GHC/Functor/ZipList.hs
=====================================
@@ -17,6 +17,25 @@ import Data.Traversable (Traversable(..))
import Data.Data (Data)
-- | Lists, but with an 'Applicative' functor based on zipping.
+--
+-- ==== __Examples__
+--
+-- In contrast to the 'Applicative' for 'GHC.List.List':
+--
+-- >>> (+) <$> [1, 2, 3] <*> [4, 5, 6]
+-- [5,6,7,6,7,8,7,8,9]
+--
+-- The Applicative instance of ZipList applies the operation
+-- by pairing up the elements, analogous to 'zipWith'N
+--
+-- >>> (+) <$> ZipList [1, 2, 3] <*> ZipList [4, 5, 6]
+-- ZipList {getZipList = [5,7,9]}
+--
+-- >>> (,,,) <$> ZipList [1, 2] <*> ZipList [3, 4] <*> ZipList [5, 6] <*> ZipList [7, 8]
+-- ZipList {getZipList = [(1,3,5,7),(2,4,6,8)]}
+--
+-- >>> ZipList [(+1), (^2), (/ 2)] <*> ZipList [5, 5, 5]
+-- ZipList {getZipList = [6.0,25.0,2.5]}
newtype ZipList a = ZipList { getZipList :: [a] }
deriving ( Show -- ^ @since 4.7.0.0
, Eq -- ^ @since 4.7.0.0
=====================================
utils/haddock
=====================================
@@ -1 +1 @@
-Subproject commit 1d230980b6a5a0ed9f83015170e20c270da51ea9
+Subproject commit e16028bdd538ccff31d732dc70855addd8aa2bfa
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/0324774ec36b61bc7ce31c91adee08b6b5992416...dba6140cb7b67bfd9f3e1343263118ffa1e43bc4
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/0324774ec36b61bc7ce31c91adee08b6b5992416...dba6140cb7b67bfd9f3e1343263118ffa1e43bc4
You're receiving this email because of your account on gitlab.haskell.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20240208/d0902a7e/attachment-0001.html>
More information about the ghc-commits
mailing list