-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Educational implementation of the STG (Spineless Tagless -- G-machine) -- -- See README.md @package stgi @version 1 -- | Useful utilities that don't really fit in a specific location. module Stg.Util -- | show with Text as codomain. -- --
-- show' = pack . show --show' :: Show a => a -> Text -- | The validation version of Either. data Validate err a Failure :: err -> Validate err a Success :: a -> Validate err a -- |
-- [a,b,c] ==> a, b, c --commaSep :: [Doc] -> Doc -- | Prefix all contained documents with a bullet symbol. bulletList :: [Doc] -> Doc -- | Add an 's' for non-singleton lists. pluralS :: [a] -> Doc instance GHC.Base.Functor (Stg.Util.Validate a) instance Data.Bifunctor.Bifunctor Stg.Util.Validate instance GHC.Base.Monoid a => GHC.Base.Applicative (Stg.Util.Validate a) -- | Prettyprinting STG elements in various formats. module Stg.Language.Prettyprint -- | The member prettyList is only used to define the instance -- Pretty a => Pretty [a]. In normal circumstances only the -- pretty function is used. class Pretty a pretty :: Pretty a => a -> Doc prettyList :: Pretty a => [a] -> Doc -- | Prettyprint a value as Text, including styles such as colours. prettyprint :: Pretty a => a -> Text -- | Prettyprint a value as Text, stripped off all style information -- such as colours. prettyprintPlain :: Pretty a => a -> Text -- | The STG language syntax tree, modeled after the description in the -- 1992 paper (link). -- -- A Program is typically created using functionality provided by -- the Stg.Parser module, as opposed to manually combining the -- data types given in this module. -- -- For plenty of comparisons of STG language source and generated parse -- trees, have a look at the Stg.Parser.QuasiQuoter module. module Stg.Language -- | An STG program consists of bindings. newtype Program Program :: Binds -> Program -- | Bindings are collections of lambda forms, indexed over variables. -- -- They exist at the top level, or as part of a let(rec) binding. newtype Binds Binds :: (Map Var LambdaForm) -> Binds -- | A lambda form unifies free and bound variables associated with a -- function body. The lambda body must not be of primitive type, as this -- would imply the value is both boxed and unboxed. -- --
-- >>> [stg| \(x) y z -> expr x z |] -- LambdaForm [Var "x"] NoUpdate [Var "y",Var "z"] (AppF (Var "expr") [AtomVar (Var "x"),AtomVar (Var "z")]) --data LambdaForm LambdaForm :: ![Var] -> !UpdateFlag -> ![Var] -> !Expr -> LambdaForm -- | Prettyprint a LambdaForm, given prettyprinters for the free -- variable list. -- -- Introduced so Closure can hijack it to display the free value -- list differently. prettyLambda :: ([Var] -> Doc) -> LambdaForm -> Doc -- | The update flag distinguishes updateable from non-updateable lambda -- forms. -- -- The former will be overwritten in-place when it is evaluated, allowing -- the calculation of a thunk to be shared among multiple uses of the -- same value. data UpdateFlag Update :: UpdateFlag NoUpdate :: UpdateFlag -- | Distinguishes let from letrec. data Rec NonRecursive :: Rec Recursive :: Rec -- | An expression in the STG language. data Expr -- | Let expression let(rec) ... in ... Let :: !Rec -> !Binds -> !Expr -> Expr -- | Case expression case ... of ... x -> y Case :: !Expr -> !Alts -> Expr -- | Function application f x y z AppF :: !Var -> ![Atom] -> Expr -- | Saturated constructor application Just a AppC :: !Constr -> ![Atom] -> Expr -- | Primitive function application + 2# AppP :: !PrimOp -> !Atom -> !Atom -> Expr -- | Literal expression 1# Lit :: !Literal -> Expr -- | List of possible alternatives in a Case expression. -- -- The list of alts has to be homogeneous. This is not ensured by the -- type system, and should be handled by the parser instead. data Alts Alts :: !NonDefaultAlts -> !DefaultAlt -> Alts -- | The part of a Case alternative that's not the default. data NonDefaultAlts -- | Used in 'case' statements that consist only of a default alternative. -- These can be useful to force or unpack values. NoNonDefaultAlts :: NonDefaultAlts -- | Algebraic alternative, like Cons x xs. AlgebraicAlts :: !(NonEmpty AlgebraicAlt) -> NonDefaultAlts -- | Primitive alternative, like 1#. PrimitiveAlts :: !(NonEmpty PrimitiveAlt) -> NonDefaultAlts -- | As in True | False data AlgebraicAlt AlgebraicAlt :: !Constr -> ![Var] -> !Expr -> AlgebraicAlt -- | As in 1#, 2#, 3# data PrimitiveAlt PrimitiveAlt :: !Literal -> !Expr -> PrimitiveAlt -- | If no viable alternative is found in a pattern match, use a -- DefaultAlt as fallback. data DefaultAlt DefaultNotBound :: !Expr -> DefaultAlt DefaultBound :: !Var -> !Expr -> DefaultAlt -- | Literals are the basis of primitive operations. newtype Literal Literal :: Integer -> Literal -- | Primitive operations. data PrimOp -- |
-- + --Add :: PrimOp -- |
-- - --Sub :: PrimOp -- |
-- * --Mul :: PrimOp -- |
-- / --Div :: PrimOp -- |
-- % --Mod :: PrimOp -- |
-- == --Eq :: PrimOp -- |
-- < --Lt :: PrimOp -- |
-- <= --Leq :: PrimOp -- |
-- > --Gt :: PrimOp -- |
-- >= --Geq :: PrimOp -- |
-- /= --Neq :: PrimOp -- | Variable. newtype Var Var :: Text -> Var -- | Smallest unit of data. Atoms unify variables and literals, and are -- what functions take as arguments. data Atom AtomVar :: !Var -> Atom AtomLit :: !Literal -> Atom -- | Constructors of algebraic data types. newtype Constr Constr :: Text -> Constr -- | The member prettyList is only used to define the instance -- Pretty a => Pretty [a]. In normal circumstances only the -- pretty function is used. class Pretty a pretty :: Pretty a => a -> Doc prettyList :: Pretty a => [a] -> Doc -- | Classify the type of a lambda form based on its shape. classify :: LambdaForm -> LambdaType -- | Possible classification of lambda forms. data LambdaType -- | Data constructor (AppC as body) LambdaCon :: LambdaType -- | Function (lambda with non-empty argument list) LambdaFun :: LambdaType -- | Thunk (everything else) LambdaThunk :: LambdaType instance Language.Haskell.TH.Syntax.Lift Stg.Language.Program instance Language.Haskell.TH.Syntax.Lift Stg.Language.Literal instance Language.Haskell.TH.Syntax.Lift Stg.Language.LambdaForm instance Language.Haskell.TH.Syntax.Lift Stg.Language.UpdateFlag instance Language.Haskell.TH.Syntax.Lift Stg.Language.Rec instance Language.Haskell.TH.Syntax.Lift Stg.Language.Expr instance Language.Haskell.TH.Syntax.Lift Stg.Language.Alts instance Language.Haskell.TH.Syntax.Lift Stg.Language.AlgebraicAlt instance Language.Haskell.TH.Syntax.Lift Stg.Language.PrimitiveAlt instance Language.Haskell.TH.Syntax.Lift Stg.Language.DefaultAlt instance Language.Haskell.TH.Syntax.Lift Stg.Language.PrimOp instance Language.Haskell.TH.Syntax.Lift Stg.Language.Atom instance Language.Haskell.TH.Syntax.Lift Stg.Language.NonDefaultAlts instance Language.Haskell.TH.Syntax.Lift Stg.Language.Binds instance Language.Haskell.TH.Syntax.Lift Stg.Language.Constr instance Language.Haskell.TH.Syntax.Lift Stg.Language.Var instance Text.PrettyPrint.ANSI.Leijen.Pretty Stg.Language.Program instance Text.PrettyPrint.ANSI.Leijen.Pretty Stg.Language.Binds instance Text.PrettyPrint.ANSI.Leijen.Pretty Stg.Language.LambdaForm instance Text.PrettyPrint.ANSI.Leijen.Pretty Stg.Language.Rec instance Text.PrettyPrint.ANSI.Leijen.Pretty Stg.Language.Expr instance Text.PrettyPrint.ANSI.Leijen.Pretty Stg.Language.Alts instance Text.PrettyPrint.ANSI.Leijen.Pretty Stg.Language.AlgebraicAlt instance Text.PrettyPrint.ANSI.Leijen.Pretty Stg.Language.PrimitiveAlt instance Text.PrettyPrint.ANSI.Leijen.Pretty Stg.Language.DefaultAlt instance Text.PrettyPrint.ANSI.Leijen.Pretty Stg.Language.Literal instance Text.PrettyPrint.ANSI.Leijen.Pretty Stg.Language.PrimOp instance Text.PrettyPrint.ANSI.Leijen.Pretty Stg.Language.Var instance Text.PrettyPrint.ANSI.Leijen.Pretty Stg.Language.Atom instance Text.PrettyPrint.ANSI.Leijen.Pretty Stg.Language.Constr instance Control.DeepSeq.NFData Stg.Language.Program instance Control.DeepSeq.NFData Stg.Language.Binds instance Control.DeepSeq.NFData Stg.Language.LambdaForm instance Control.DeepSeq.NFData Stg.Language.UpdateFlag instance Control.DeepSeq.NFData Stg.Language.Rec instance Control.DeepSeq.NFData Stg.Language.Expr instance Control.DeepSeq.NFData Stg.Language.Alts instance Control.DeepSeq.NFData Stg.Language.NonDefaultAlts instance Control.DeepSeq.NFData Stg.Language.AlgebraicAlt instance Control.DeepSeq.NFData Stg.Language.PrimitiveAlt instance Control.DeepSeq.NFData Stg.Language.DefaultAlt instance Control.DeepSeq.NFData Stg.Language.Literal instance Control.DeepSeq.NFData Stg.Language.PrimOp instance Control.DeepSeq.NFData Stg.Language.Var instance Control.DeepSeq.NFData Stg.Language.Atom instance Control.DeepSeq.NFData Stg.Language.Constr instance GHC.Generics.Constructor Stg.Language.C1_0Program instance GHC.Generics.Datatype Stg.Language.D1Program instance GHC.Generics.Constructor Stg.Language.C1_0LambdaForm instance GHC.Generics.Datatype Stg.Language.D1LambdaForm instance GHC.Generics.Constructor Stg.Language.C1_0Binds instance GHC.Generics.Datatype Stg.Language.D1Binds instance GHC.Generics.Constructor Stg.Language.C1_0AlgebraicAlt instance GHC.Generics.Datatype Stg.Language.D1AlgebraicAlt instance GHC.Generics.Constructor Stg.Language.C1_0PrimitiveAlt instance GHC.Generics.Datatype Stg.Language.D1PrimitiveAlt instance GHC.Generics.Constructor Stg.Language.C1_2NonDefaultAlts instance GHC.Generics.Constructor Stg.Language.C1_1NonDefaultAlts instance GHC.Generics.Constructor Stg.Language.C1_0NonDefaultAlts instance GHC.Generics.Datatype Stg.Language.D1NonDefaultAlts instance GHC.Generics.Constructor Stg.Language.C1_1DefaultAlt instance GHC.Generics.Constructor Stg.Language.C1_0DefaultAlt instance GHC.Generics.Datatype Stg.Language.D1DefaultAlt instance GHC.Generics.Constructor Stg.Language.C1_0Alts instance GHC.Generics.Datatype Stg.Language.D1Alts instance GHC.Generics.Constructor Stg.Language.C1_5Expr instance GHC.Generics.Constructor Stg.Language.C1_4Expr instance GHC.Generics.Constructor Stg.Language.C1_3Expr instance GHC.Generics.Constructor Stg.Language.C1_2Expr instance GHC.Generics.Constructor Stg.Language.C1_1Expr instance GHC.Generics.Constructor Stg.Language.C1_0Expr instance GHC.Generics.Datatype Stg.Language.D1Expr instance GHC.Generics.Constructor Stg.Language.C1_0Constr instance GHC.Generics.Datatype Stg.Language.D1Constr instance GHC.Generics.Constructor Stg.Language.C1_1Atom instance GHC.Generics.Constructor Stg.Language.C1_0Atom instance GHC.Generics.Datatype Stg.Language.D1Atom instance GHC.Generics.Constructor Stg.Language.C1_0Var instance GHC.Generics.Datatype Stg.Language.D1Var instance GHC.Generics.Constructor Stg.Language.C1_10PrimOp instance GHC.Generics.Constructor Stg.Language.C1_9PrimOp instance GHC.Generics.Constructor Stg.Language.C1_8PrimOp instance GHC.Generics.Constructor Stg.Language.C1_7PrimOp instance GHC.Generics.Constructor Stg.Language.C1_6PrimOp instance GHC.Generics.Constructor Stg.Language.C1_5PrimOp instance GHC.Generics.Constructor Stg.Language.C1_4PrimOp instance GHC.Generics.Constructor Stg.Language.C1_3PrimOp instance GHC.Generics.Constructor Stg.Language.C1_2PrimOp instance GHC.Generics.Constructor Stg.Language.C1_1PrimOp instance GHC.Generics.Constructor Stg.Language.C1_0PrimOp instance GHC.Generics.Datatype Stg.Language.D1PrimOp instance GHC.Generics.Constructor Stg.Language.C1_0Literal instance GHC.Generics.Datatype Stg.Language.D1Literal instance GHC.Generics.Constructor Stg.Language.C1_1Rec instance GHC.Generics.Constructor Stg.Language.C1_0Rec instance GHC.Generics.Datatype Stg.Language.D1Rec instance GHC.Generics.Constructor Stg.Language.C1_1UpdateFlag instance GHC.Generics.Constructor Stg.Language.C1_0UpdateFlag instance GHC.Generics.Datatype Stg.Language.D1UpdateFlag instance GHC.Generics.Generic Stg.Language.Program instance GHC.Show.Show Stg.Language.Program instance GHC.Classes.Ord Stg.Language.Program instance GHC.Classes.Eq Stg.Language.Program instance GHC.Generics.Generic Stg.Language.LambdaForm instance GHC.Show.Show Stg.Language.LambdaForm instance GHC.Classes.Ord Stg.Language.LambdaForm instance GHC.Classes.Eq Stg.Language.LambdaForm instance GHC.Generics.Generic Stg.Language.Binds instance GHC.Classes.Ord Stg.Language.Binds instance GHC.Classes.Eq Stg.Language.Binds instance GHC.Generics.Generic Stg.Language.AlgebraicAlt instance GHC.Show.Show Stg.Language.AlgebraicAlt instance GHC.Classes.Ord Stg.Language.AlgebraicAlt instance GHC.Classes.Eq Stg.Language.AlgebraicAlt instance GHC.Generics.Generic Stg.Language.PrimitiveAlt instance GHC.Show.Show Stg.Language.PrimitiveAlt instance GHC.Classes.Ord Stg.Language.PrimitiveAlt instance GHC.Classes.Eq Stg.Language.PrimitiveAlt instance GHC.Generics.Generic Stg.Language.NonDefaultAlts instance GHC.Show.Show Stg.Language.NonDefaultAlts instance GHC.Classes.Ord Stg.Language.NonDefaultAlts instance GHC.Classes.Eq Stg.Language.NonDefaultAlts instance GHC.Generics.Generic Stg.Language.DefaultAlt instance GHC.Show.Show Stg.Language.DefaultAlt instance GHC.Classes.Ord Stg.Language.DefaultAlt instance GHC.Classes.Eq Stg.Language.DefaultAlt instance GHC.Generics.Generic Stg.Language.Alts instance GHC.Show.Show Stg.Language.Alts instance GHC.Classes.Ord Stg.Language.Alts instance GHC.Classes.Eq Stg.Language.Alts instance GHC.Generics.Generic Stg.Language.Expr instance GHC.Show.Show Stg.Language.Expr instance GHC.Classes.Ord Stg.Language.Expr instance GHC.Classes.Eq Stg.Language.Expr instance GHC.Generics.Generic Stg.Language.Constr instance GHC.Show.Show Stg.Language.Constr instance GHC.Classes.Ord Stg.Language.Constr instance GHC.Classes.Eq Stg.Language.Constr instance GHC.Generics.Generic Stg.Language.Atom instance GHC.Show.Show Stg.Language.Atom instance GHC.Classes.Ord Stg.Language.Atom instance GHC.Classes.Eq Stg.Language.Atom instance GHC.Generics.Generic Stg.Language.Var instance GHC.Show.Show Stg.Language.Var instance GHC.Classes.Ord Stg.Language.Var instance GHC.Classes.Eq Stg.Language.Var instance GHC.Enum.Enum Stg.Language.PrimOp instance GHC.Enum.Bounded Stg.Language.PrimOp instance GHC.Generics.Generic Stg.Language.PrimOp instance GHC.Show.Show Stg.Language.PrimOp instance GHC.Classes.Ord Stg.Language.PrimOp instance GHC.Classes.Eq Stg.Language.PrimOp instance GHC.Generics.Generic Stg.Language.Literal instance GHC.Show.Show Stg.Language.Literal instance GHC.Classes.Ord Stg.Language.Literal instance GHC.Classes.Eq Stg.Language.Literal instance GHC.Enum.Bounded Stg.Language.Rec instance GHC.Enum.Enum Stg.Language.Rec instance GHC.Generics.Generic Stg.Language.Rec instance GHC.Show.Show Stg.Language.Rec instance GHC.Classes.Ord Stg.Language.Rec instance GHC.Classes.Eq Stg.Language.Rec instance GHC.Enum.Bounded Stg.Language.UpdateFlag instance GHC.Enum.Enum Stg.Language.UpdateFlag instance GHC.Generics.Generic Stg.Language.UpdateFlag instance GHC.Show.Show Stg.Language.UpdateFlag instance GHC.Classes.Ord Stg.Language.UpdateFlag instance GHC.Classes.Eq Stg.Language.UpdateFlag instance GHC.Show.Show Stg.Language.LambdaType instance GHC.Classes.Ord Stg.Language.LambdaType instance GHC.Classes.Eq Stg.Language.LambdaType instance GHC.Base.Monoid Stg.Language.Program instance GHC.Base.Monoid Stg.Language.Binds instance GHC.Show.Show Stg.Language.Binds instance Text.PrettyPrint.ANSI.Leijen.Pretty Stg.Language.LambdaType instance Data.String.IsString Stg.Language.Var instance Data.String.IsString Stg.Language.Constr -- | A parser for the STG language, modeled after the grammar given in the -- description in the 1992 paper (link) with a couple of -- differences to enhance usability: -- --
-- >>> parse program "id = \\x -> x" -- Right (Program (Binds [(Var "id",LambdaForm [] NoUpdate [Var "x"] (AppF (Var "x") []))])) --parse :: StgParser ast -> Text -> Either Doc ast -- | A parser for an STG syntax element. data StgParser ast -- | Parse an STG program. program :: (Monad parser, TokenParsing parser) => parser Program -- | Parse a collection of bindings, used by let(rec) expressions -- and at the top level of a program. binds :: (Monad parser, TokenParsing parser) => parser Binds -- | Parse a lambda form, consisting of a list of free variables, and -- update flag, a list of bound variables, and the function body. lambdaForm :: (Monad parser, TokenParsing parser) => parser LambdaForm -- | Parse an expression, which can be -- --
-- Nil -> ... -- Cons x xs -> ... ---- --
-- 1# -> ... -- 2# -> ... --nonDefaultAlts :: (Monad parser, TokenParsing parser) => parser NonDefaultAlts -- | Parse a single algebraic alternative. -- --
-- Cons x xs -> ... --algebraicAlt :: (Monad parser, TokenParsing parser) => parser AlgebraicAlt -- | Parse a single primitive alternative, such as 1#. -- --
-- 1# -> ... --primitiveAlt :: (Monad parser, TokenParsing parser) => parser PrimitiveAlt -- | Parse the default alternative, taken if none of the other alternatives -- in a case expression match. -- --
-- default -> ... ---- --
-- v -> ... --defaultAlt :: (Monad parser, TokenParsing parser) => parser DefaultAlt literal :: TokenParsing parser => parser Literal -- | Parse a primitive operation. -- --
-- +# --primOp :: TokenParsing parser => parser PrimOp atom :: (Monad parser, TokenParsing parser) => parser Atom -- | Parse a variable identifier. Variables start with a lower-case letter -- or _, followed by a string consisting of alphanumeric -- characters or ', _. var :: (Monad parser, TokenParsing parser) => parser Var -- | Parse a constructor identifier. Constructors follow the same naming -- conventions as variables, but start with an upper-case character -- instead, and may end with a # symbol. con :: (Monad parser, TokenParsing parser) => parser Constr instance GHC.Base.Monad Stg.Parser.Parser.StgParser instance GHC.Base.Functor Stg.Parser.Parser.StgParser instance GHC.Base.Applicative Stg.Parser.Parser.StgParser instance GHC.Base.Alternative Stg.Parser.Parser.StgParser instance Text.Parser.Combinators.Parsing Stg.Parser.Parser.StgParser instance Text.Parser.Char.CharParsing Stg.Parser.Parser.StgParser instance Text.Parser.Token.TokenParsing Stg.Parser.Parser.StgParser -- | Quasiquoters for easier generation of STG syntax trees. The stg -- quoter is most convenient, I suggest you use it unless you have a -- reason not to. module Stg.Parser.QuasiQuoter -- | Heuristic quasiquoter for STG language elements. Tries a number of -- parsers, and will use the first successful one. -- -- To gain more fine-grained control over what the input should be parsed -- to, use one of the non-heuristic quoters, such as stgProgram -- or stgLambdaForm. These will also give you much better error -- messages than merely "doesn't work". -- --
-- >>> [stg| id = \x -> x |] -- Program (Binds [(Var "id",LambdaForm [] NoUpdate [Var "x"] (AppF (Var "x") []))]) ---- --
-- >>> [stg| \x -> x |] -- LambdaForm [] NoUpdate [Var "x"] (AppF (Var "x") []) ---- --
-- >>> [stg| x |] -- AppF (Var "x") [] --stg :: QuasiQuoter -- | Quasiquoter for Programs. -- --
-- >>> [program| id = \x -> x |] -- Program (Binds [(Var "id",LambdaForm [] NoUpdate [Var "x"] (AppF (Var "x") []))]) --program :: QuasiQuoter -- | Quasiquoter for Binds. -- --
-- >>> [binds| id = \x -> x |] -- (Binds [(Var "id",LambdaForm [] NoUpdate [Var "x"] (AppF (Var "x") []))]) --binds :: QuasiQuoter -- | Quasiquoter for LambdaForms. -- --
-- >>> [lambdaForm| \x -> x |] -- LambdaForm [] NoUpdate [Var "x"] (AppF (Var "x") []) --lambdaForm :: QuasiQuoter -- | Quasiquoter for Expressions. -- --
-- >>> [expr| f x y z |] -- AppF (Var "f") [AtomVar (Var "x"),AtomVar (Var "y"),AtomVar (Var "z")] --expr :: QuasiQuoter -- | Quasiquoter for Alts. -- --
-- >>> [alts| Just x -> True; default -> False |] -- Alts (AlgebraicAlts (AlgebraicAlt (Constr "Just") [Var "x"] (AppC (Constr "True") []) :| [])) (DefaultNotBound (AppC (Constr "False") [])) ---- --
-- >>> [alts| 0# -> True; default -> False |] -- Alts (PrimitiveAlts (PrimitiveAlt (Literal 0) (AppC (Constr "True") []) :| [])) (DefaultNotBound (AppC (Constr "False") [])) --alts :: QuasiQuoter -- | Quasiquoter for Alt. -- --
-- >>> [nonDefaultAlts| Just x -> True; Nothing -> False; |] -- AlgebraicAlts (AlgebraicAlt (Constr "Just") [Var "x"] (AppC (Constr "True") []) :| [AlgebraicAlt (Constr "Nothing") [] (AppC (Constr "False") [])]) ---- --
-- >>> [nonDefaultAlts| 0# -> False; 1# -> True; |] -- PrimitiveAlts (PrimitiveAlt (Literal 0) (AppC (Constr "False") []) :| [PrimitiveAlt (Literal 1) (AppC (Constr "True") [])]) --nonDefaultAlts :: QuasiQuoter -- | Quasiquoter for AlgebraicAlts. -- --
-- >>> [algebraicAlt| Just x -> x; |] -- AlgebraicAlt (Constr "Just") [Var "x"] (AppF (Var "x") []) --algebraicAlt :: QuasiQuoter -- | Quasiquoter for PrimitiveAlts. -- --
-- >>> [primitiveAlt| 1# -> x; |] -- PrimitiveAlt (Literal 1) (AppF (Var "x") []) --primitiveAlt :: QuasiQuoter -- | Quasiquoter for DefaultAlts. -- --
-- >>> [defaultAlt| default -> x |] -- DefaultNotBound (AppF (Var "x") []) ---- --
-- >>> [defaultAlt| x -> x |] -- DefaultBound (Var "x") (AppF (Var "x") []) --defaultAlt :: QuasiQuoter -- | Quasiquoter for Literals. -- --
-- >>> [literal| 1# |] -- Literal 1 --literal :: QuasiQuoter -- | Quasiquoter for PrimOps. -- --
-- >>> [primOp| +# |] -- Add --primOp :: QuasiQuoter -- | Quasiquoter for Atoms. -- --
-- >>> [atom| x |] -- AtomVar (Var "x") --atom :: QuasiQuoter module Stg.Prelude.Maybe -- | Nothing as a top-level closure. -- --
-- nothing : Maybe a --nothing :: Program -- | Deconstructor of the Maybe type. -- --
-- maybe : b -> (a -> b) -> Maybe a -> b --maybe :: Program -- | Boolean functions, like in Data.Bool. module Stg.Prelude.Bool -- | Binary and. Haskell's (&&). -- --
-- && : Bool -> Bool -> Bool --and2 :: Program -- | Binary or. Haskell's (||). -- --
-- || : Bool -> Bool -> Bool --or2 :: Program -- | Binary negation. -- --
-- not : Bool -> Bool --not :: Program -- | Boolean deconstructor. -- --
-- bool f _ False = f -- bool _ t True = t ---- --
-- bool : a -> a -> Bool -> a --bool :: Program -- | Boolean equality. eq_Bool :: Program module Stg.Prelude.Function -- | Finally I can define seq directly! :-) -- -- Note that this function is less powerful than GHC's seq, since -- STG does not have a rule to force functions, only expressions that -- reduce to an algebraic or primitive value. This leads to the fact that -- STG's seq is less powerful than Haskell's, since in Haskell -- --
-- seq (const ()) () = () ---- -- whereas in the STG -- --
-- constUnit = (x) -> Unit (); -- seq (constUnit, Unit) = ERROR --seq :: Program -- | Identity function. -- --
-- id : a -> a --id :: Program -- | Constant function. -- --
-- Const : a -> b -> a --const :: Program -- | Function composition. -- --
-- compose : (b -> c) -> (a -> b) -> a -> c --compose :: Program -- | The fixed point combinator. -- --
-- fix : (a -> a) -> a --fix :: Program module Stg.Prelude.Number add :: Program sub :: Program mul :: Program div :: Program mod :: Program eq_Int :: Program lt_Int :: Program leq_Int :: Program gt_Int :: Program geq_Int :: Program neq_Int :: Program min :: Program max :: Program module Stg.Prelude.List -- | The empty list as a top-level closure. -- --
-- nil : [a] --nil :: Program -- | Concatenate two lists. Haskell's (++). -- --
-- concat2 : [a] -> [a] -> [a] --concat2 :: Program -- | reverse a list. -- --
-- reverse [1,2,3] = [3,2,1] ---- --
-- reverse : [a] -> [a] --reverse :: Program -- | Lazy left list fold. Provided mostly for seeing how it causes stack -- overflows. -- --
-- foldl : (b -> a -> b) -> b -> [a] -> b --foldl :: Program -- | Strict left list fold. -- -- Careful: the STG only supports primitive and algebraic case -- scrutinees. As a result, you can only hand primitive or algebraic -- b values to this function or it will fail! -- --
-- foldl' : (b -> a -> b) -> b -> [a] -> b --foldl' :: Program -- | Right list fold. -- --
-- foldr : (a -> b -> b) -> b -> [a] -> b --foldr :: Program -- | Build a list by repeatedly applying a function to an initial value. -- --
-- iterate f x = [x, f x, f (f x), ...] ---- --
-- iterate : (a -> a) -> a -> [a] --iterate :: Program -- | Infinite list created by repeating an initial (non-empty) list. -- --
-- cycle [x,y,z] = [x,y,z, x,y,z, x,y,z, ...] ---- --
-- cycle : [a] -> [a] --cycle :: Program -- | Take n elements form the beginning of a list. -- --
-- take 3 [1..] = [1,2,3] ---- --
-- take : Int -> [a] -> [a] --take :: Program -- | Keep only the elements for which a predicate holds. -- --
-- filter even [1..] = [2, 4, 6, ...] ---- --
-- filter : (a -> Bool) -> [a] -> [a] --filter :: Program -- | Repeat a single element infinitely. -- --
-- repeat 1 = [1, 1, 1, ...] ---- --
-- repeat : a -> [a] --repeat :: Program -- | Repeat a single element a number of times. -- --
-- replicate 3 1 = [1, 1, 1] ---- --
-- replicate : Int -> a -> [a] --replicate :: Program -- | Haskell's Prelude sort function at the time of implementing this. Not -- quite as pretty as the Haskell version, but functionally equivalent. -- :-) -- -- This implementation is particularly efficient when the input contains -- runs of already sorted elements. For comparison, sorting [1..100] -- takes 6496 steps, whereas naiveSort requires 268082. -- --
-- sort : [Int] -> [Int] --sort :: Program -- | That Haskell sort function often misleadingly referred to as -- "quicksort". -- --
-- naiveSort : [Int] -> [Int] --naiveSort :: Program -- | Apply a function to each element of a list. -- --
-- map : (a -> b) -> [a] -> [b] --map :: Program -- | Equality of lists of integers. -- --
-- equals_List_Int : [Int] -> [Int] -> Bool --equals_List_Int :: Program -- | Length of a list. -- --
-- length : [a] -> Int --length :: Program -- | Zip two lists into one. If one list is longer than the other ignore -- the exceeding elements. -- --
-- zip [1,2,3,4,5] [10,20,30] ==> [(1,10),(2,20),(3,30)] -- -- zip xs ys = zipWith Pair xs ys ---- --
-- zip : [a] -> [b] -> [(a,b)] --zip :: Program -- | Zip two lists into one using a user-specified combining function. If -- one list is longer than the other ignore the exceeding elements. -- --
-- zipWith (+) [1,2,3,4,5] [10,20,30] ==> [11,22,33] -- -- zipWith f xs ys = map f (zip xs ys) ---- --
-- zipWith : (a -> b -> c) -> [a] -> [b] -> [c] --zipWith :: Program -- | Force the spine of a list. -- --
-- forceSpine :: [a] -> [a] --forceSpine :: Program -- | Convert Haskell values to STG values. module Stg.Marshal.ToStg -- | Convert a Haskell value to an STG binding. -- -- Instances of this class should have a corresponding FromStg -- instance to retrieve a value fom the program, with the two being -- inverse to each other (up to forcing the generated thunks). -- -- This class contains a helper function, toStgWithGlobals, this -- is hidden from the outside. If you want to write your own instance, -- have a look at the source for documentation. class ToStg value where toStg var val = let (globals, actualDef) = runWriter (toStgWithGlobals var val) in globals <> actualDef toStgWithGlobals var val = pure (toStg var val) toStg :: ToStg value => Var -> value -> Program -- | Some definitions, such as the one for lists, require certain global -- values to be present (such as nil). In order to avoid duplicate -- definitions, this function allows defining top-level elements using -- Writers tell function. toStgWithGlobals :: ToStg value => Var -> value -> Writer Program Program instance Stg.Marshal.ToStg.ToStg () instance Stg.Marshal.ToStg.ToStg GHC.Integer.Type.Integer instance Stg.Marshal.ToStg.ToStg GHC.Types.Int instance Stg.Marshal.ToStg.ToStg GHC.Types.Bool instance Stg.Marshal.ToStg.ToStg a => Stg.Marshal.ToStg.ToStg (GHC.Base.Maybe a) instance (Stg.Marshal.ToStg.ToStg a, Stg.Marshal.ToStg.ToStg b) => Stg.Marshal.ToStg.ToStg (Data.Either.Either a b) instance Stg.Marshal.ToStg.ToStg a => Stg.Marshal.ToStg.ToStg [a] instance (Stg.Marshal.ToStg.ToStg a, Stg.Marshal.ToStg.ToStg b) => Stg.Marshal.ToStg.ToStg (a, b) instance (Stg.Marshal.ToStg.ToStg a, Stg.Marshal.ToStg.ToStg b, Stg.Marshal.ToStg.ToStg c) => Stg.Marshal.ToStg.ToStg (a, b, c) instance (Stg.Marshal.ToStg.ToStg a, Stg.Marshal.ToStg.ToStg b, Stg.Marshal.ToStg.ToStg c, Stg.Marshal.ToStg.ToStg d) => Stg.Marshal.ToStg.ToStg (a, b, c, d) instance (Stg.Marshal.ToStg.ToStg a, Stg.Marshal.ToStg.ToStg b, Stg.Marshal.ToStg.ToStg c, Stg.Marshal.ToStg.ToStg d, Stg.Marshal.ToStg.ToStg e) => Stg.Marshal.ToStg.ToStg (a, b, c, d, e) module Stg.Prelude.Tuple -- | First element of a tuple. -- --
-- fst : (a,b) -> a --fst :: Program -- | Second element of a tuple. -- --
-- snd : (a,b) -> a --snd :: Program -- | Convert an uncurried function to a curried one. -- --
-- curry : ((a, b) -> c) -> a -> b -> c --curry :: Program -- | Convert a curried function to an uncurried one. -- --
-- uncurry : (a -> b -> c) -> (a, b) -> c --uncurry :: Program -- | Swap the elements of a tuple. -- --
-- swap : (a,b) -> (b,a) --swap :: Program equals_Pair_Int :: Program -- | Common Haskell functions, translated to STG. Use the Monoid -- instance for Program to mix them. -- -- This module should be imported qualified, since it heavily conflicts -- with the standard Haskell Prelude. module Stg.Prelude -- | Deconstructor of the Maybe type. -- --
-- maybe : b -> (a -> b) -> Maybe a -> b --maybe :: Program -- | Nothing as a top-level closure. -- --
-- nothing : Maybe a --nothing :: Program -- | The empty list as a top-level closure. -- --
-- nil : [a] --nil :: Program -- | Concatenate two lists. Haskell's (++). -- --
-- concat2 : [a] -> [a] -> [a] --concat2 :: Program -- | reverse a list. -- --
-- reverse [1,2,3] = [3,2,1] ---- --
-- reverse : [a] -> [a] --reverse :: Program -- | Lazy left list fold. Provided mostly for seeing how it causes stack -- overflows. -- --
-- foldl : (b -> a -> b) -> b -> [a] -> b --foldl :: Program -- | Strict left list fold. -- -- Careful: the STG only supports primitive and algebraic case -- scrutinees. As a result, you can only hand primitive or algebraic -- b values to this function or it will fail! -- --
-- foldl' : (b -> a -> b) -> b -> [a] -> b --foldl' :: Program -- | Right list fold. -- --
-- foldr : (a -> b -> b) -> b -> [a] -> b --foldr :: Program -- | Build a list by repeatedly applying a function to an initial value. -- --
-- iterate f x = [x, f x, f (f x), ...] ---- --
-- iterate : (a -> a) -> a -> [a] --iterate :: Program -- | Infinite list created by repeating an initial (non-empty) list. -- --
-- cycle [x,y,z] = [x,y,z, x,y,z, x,y,z, ...] ---- --
-- cycle : [a] -> [a] --cycle :: Program -- | Take n elements form the beginning of a list. -- --
-- take 3 [1..] = [1,2,3] ---- --
-- take : Int -> [a] -> [a] --take :: Program -- | Keep only the elements for which a predicate holds. -- --
-- filter even [1..] = [2, 4, 6, ...] ---- --
-- filter : (a -> Bool) -> [a] -> [a] --filter :: Program -- | Repeat a single element infinitely. -- --
-- repeat 1 = [1, 1, 1, ...] ---- --
-- repeat : a -> [a] --repeat :: Program -- | Repeat a single element a number of times. -- --
-- replicate 3 1 = [1, 1, 1] ---- --
-- replicate : Int -> a -> [a] --replicate :: Program -- | Haskell's Prelude sort function at the time of implementing this. Not -- quite as pretty as the Haskell version, but functionally equivalent. -- :-) -- -- This implementation is particularly efficient when the input contains -- runs of already sorted elements. For comparison, sorting [1..100] -- takes 6496 steps, whereas naiveSort requires 268082. -- --
-- sort : [Int] -> [Int] --sort :: Program -- | That Haskell sort function often misleadingly referred to as -- "quicksort". -- --
-- naiveSort : [Int] -> [Int] --naiveSort :: Program -- | Apply a function to each element of a list. -- --
-- map : (a -> b) -> [a] -> [b] --map :: Program -- | Length of a list. -- --
-- length : [a] -> Int --length :: Program -- | Zip two lists into one. If one list is longer than the other ignore -- the exceeding elements. -- --
-- zip [1,2,3,4,5] [10,20,30] ==> [(1,10),(2,20),(3,30)] -- -- zip xs ys = zipWith Pair xs ys ---- --
-- zip : [a] -> [b] -> [(a,b)] --zip :: Program -- | Zip two lists into one using a user-specified combining function. If -- one list is longer than the other ignore the exceeding elements. -- --
-- zipWith (+) [1,2,3,4,5] [10,20,30] ==> [11,22,33] -- -- zipWith f xs ys = map f (zip xs ys) ---- --
-- zipWith : (a -> b -> c) -> [a] -> [b] -> [c] --zipWith :: Program -- | Force the spine of a list. -- --
-- forceSpine :: [a] -> [a] --forceSpine :: Program -- | Equality of lists of integers. -- --
-- equals_List_Int : [Int] -> [Int] -> Bool --equals_List_Int :: Program -- | First element of a tuple. -- --
-- fst : (a,b) -> a --fst :: Program -- | Second element of a tuple. -- --
-- snd : (a,b) -> a --snd :: Program -- | Convert an uncurried function to a curried one. -- --
-- curry : ((a, b) -> c) -> a -> b -> c --curry :: Program -- | Convert a curried function to an uncurried one. -- --
-- uncurry : (a -> b -> c) -> (a, b) -> c --uncurry :: Program -- | Swap the elements of a tuple. -- --
-- swap : (a,b) -> (b,a) --swap :: Program equals_Pair_Int :: Program -- | Binary and. Haskell's (&&). -- --
-- && : Bool -> Bool -> Bool --and2 :: Program -- | Binary or. Haskell's (||). -- --
-- || : Bool -> Bool -> Bool --or2 :: Program -- | Binary negation. -- --
-- not : Bool -> Bool --not :: Program -- | Boolean deconstructor. -- --
-- bool f _ False = f -- bool _ t True = t ---- --
-- bool : a -> a -> Bool -> a --bool :: Program -- | Boolean equality. eq_Bool :: Program add :: Program sub :: Program mul :: Program div :: Program mod :: Program eq_Int :: Program lt_Int :: Program leq_Int :: Program gt_Int :: Program geq_Int :: Program neq_Int :: Program min :: Program max :: Program -- | Finally I can define seq directly! :-) -- -- Note that this function is less powerful than GHC's seq, since -- STG does not have a rule to force functions, only expressions that -- reduce to an algebraic or primitive value. This leads to the fact that -- STG's seq is less powerful than Haskell's, since in Haskell -- --
-- seq (const ()) () = () ---- -- whereas in the STG -- --
-- constUnit = (x) -> Unit (); -- seq (constUnit, Unit) = ERROR --seq :: Program -- | Identity function. -- --
-- id : a -> a --id :: Program -- | Constant function. -- --
-- Const : a -> b -> a --const :: Program -- | Function composition. -- --
-- compose : (b -> c) -> (a -> b) -> a -> c --compose :: Program -- | The fixed point combinator. -- --
-- fix : (a -> a) -> a --fix :: Program -- | Force a value to normal form and return it. -- -- This function makes heavy use of the fact that the STG is untyped. It -- currently supports the following types: -- --
-- last (evalsUntil ...) ≡ evalUntil --evalUntil :: RunForSteps -> HaltIf -> PerformGc -> StgState -> StgState -- | Evaluate the STG, and record all intermediate states. -- --
-- evalsUntil ≈ unfoldr evalUntil --evalsUntil :: RunForSteps -> HaltIf -> PerformGc -> StgState -> NonEmpty StgState -- | Check whether a state is terminal. terminated :: StgState -> Bool -- | Predicate to decide whether the machine should halt. newtype HaltIf HaltIf :: (StgState -> Bool) -> HaltIf -- | Predicate to decide whether the machine should halt. data RunForSteps -- | Do not terminate based on the number of steps RunIndefinitely :: RunForSteps RunForMaxSteps :: Integer -> RunForSteps garbageCollect :: GarbageCollectionAlgorithm -> StgState -> StgState -- | Decide whether garbage collection should be attempted, and with which -- algorithm. newtype PerformGc PerformGc :: (StgState -> Maybe GarbageCollectionAlgorithm) -> PerformGc data GarbageCollectionAlgorithm -- | Remove all unused addresses, without moving the others. triStateTracing :: GarbageCollectionAlgorithm -- | Remove all unused addresses by moving them to a safe location. twoSpaceCopying :: GarbageCollectionAlgorithm -- | Extract Haskell values from running STG programs. module Stg.Marshal.FromStg -- | Look up the value of a global variable. -- -- Instances of this class should have a corresponding ToStg -- instance to inject a value into the program, with the two being -- inverse to each other (up to forcing the generated thunks). class FromStg value where fromStg stgState = globalVal stgState (\case { PrimInt {} -> Left TypeMismatch Addr addr -> fromStgAddr stgState addr }) fromStgPrim _ = Left TypeMismatch -- | Retrieve the value of a global variable. fromStg :: FromStg value => StgState -> Var -> Either FromStgError value -- | Retrieve the value of a heap address. fromStgAddr :: FromStg value => StgState -> MemAddr -> Either FromStgError value -- | Used only for looking up primitive integers. fromStgPrim :: FromStg value => Integer -> Either FromStgError value data FromStgError -- | e.g. asking for an Int# at an address that contains a -- Cons TypeMismatch :: FromStgError -- | Tried retrieving a non-constructor IsWrongLambdaType :: LambdaType -> FromStgError -- | Tried retrieving a black hole IsBlackhole :: FromStgError -- | e.g. Cons x y z BadArity :: FromStgError -- | An unsuccessful variable lookup NotFound :: NotInScope -> FromStgError AddrNotOnHeap :: FromStgError -- | None of the given alternatives matched the given constructor, e.g. -- when trying to receive a Left as a Just NoConstructorMatch :: FromStgError instance GHC.Show.Show Stg.Marshal.FromStg.FromStgError instance GHC.Classes.Ord Stg.Marshal.FromStg.FromStgError instance GHC.Classes.Eq Stg.Marshal.FromStg.FromStgError instance Stg.Marshal.FromStg.FromStg () instance Stg.Marshal.FromStg.FromStg GHC.Types.Bool instance Stg.Marshal.FromStg.FromStg GHC.Integer.Type.Integer instance (Stg.Marshal.FromStg.FromStg a, Stg.Marshal.FromStg.FromStg b) => Stg.Marshal.FromStg.FromStg (a, b) instance (Stg.Marshal.FromStg.FromStg a, Stg.Marshal.FromStg.FromStg b, Stg.Marshal.FromStg.FromStg c) => Stg.Marshal.FromStg.FromStg (a, b, c) instance (Stg.Marshal.FromStg.FromStg a, Stg.Marshal.FromStg.FromStg b, Stg.Marshal.FromStg.FromStg c, Stg.Marshal.FromStg.FromStg d) => Stg.Marshal.FromStg.FromStg (a, b, c, d) instance (Stg.Marshal.FromStg.FromStg a, Stg.Marshal.FromStg.FromStg b, Stg.Marshal.FromStg.FromStg c, Stg.Marshal.FromStg.FromStg d, Stg.Marshal.FromStg.FromStg e) => Stg.Marshal.FromStg.FromStg (a, b, c, d, e) instance Stg.Marshal.FromStg.FromStg a => Stg.Marshal.FromStg.FromStg (GHC.Base.Maybe a) instance (Stg.Marshal.FromStg.FromStg a, Stg.Marshal.FromStg.FromStg b) => Stg.Marshal.FromStg.FromStg (Data.Either.Either a b) instance Stg.Marshal.FromStg.FromStg a => Stg.Marshal.FromStg.FromStg [a] -- | Convert Haskell values to STG values and back. -- -- This module is what users should be using - it reexports only the safe -- classes. module Stg.Marshal -- | Convert a Haskell value to an STG binding. -- -- Instances of this class should have a corresponding FromStg -- instance to retrieve a value fom the program, with the two being -- inverse to each other (up to forcing the generated thunks). -- -- This class contains a helper function, toStgWithGlobals, this -- is hidden from the outside. If you want to write your own instance, -- have a look at the source for documentation. class ToStg value where toStg var val = let (globals, actualDef) = runWriter (toStgWithGlobals var val) in globals <> actualDef toStgWithGlobals var val = pure (toStg var val) toStg :: ToStg value => Var -> value -> Program -- | Look up the value of a global variable. -- -- Instances of this class should have a corresponding ToStg -- instance to inject a value into the program, with the two being -- inverse to each other (up to forcing the generated thunks). class FromStg value where fromStg stgState = globalVal stgState (\case { PrimInt {} -> Left TypeMismatch Addr addr -> fromStgAddr stgState addr }) fromStgPrim _ = Left TypeMismatch -- | Retrieve the value of a global variable. fromStg :: FromStg value => StgState -> Var -> Either FromStgError value data FromStgError -- | e.g. asking for an Int# at an address that contains a -- Cons TypeMismatch :: FromStgError -- | Tried retrieving a non-constructor IsWrongLambdaType :: LambdaType -> FromStgError -- | Tried retrieving a black hole IsBlackhole :: FromStgError -- | e.g. Cons x y z BadArity :: FromStgError -- | An unsuccessful variable lookup NotFound :: NotInScope -> FromStgError AddrNotOnHeap :: FromStgError -- | None of the given alternatives matched the given constructor, e.g. -- when trying to receive a Left as a Just NoConstructorMatch :: FromStgError -- | A collection of example programs that might be interesting to look at -- during execution. module Stg.ExamplePrograms -- | A program that adds two numbers. addTwoNumbers :: Integer -> Integer -> Program -- | A program that measures the length of a list. calculateLength :: [Integer] -> Program -- | Sum up a list of Integers using -- --
-- sum = foldl' (+) 0 ---- -- This is a good way to sum up a list in Haskell, as it runs in constant -- space. sum_foldl' :: [Integer] -> Program -- | Sum up a list of Integers using -- --
-- sum = foldl' (+) 0 ---- -- where foldl' is implemented via foldr as -- --
-- foldl' f z ys = foldr (x xs acc -> xs $! f acc x) id ys z ---- -- which is a standard "foldl' in terms of foldr" -- definition. This definition is denotationally equivalent to the -- standard foldl', but has a bit more computational overhead. sum_foldl'ViaFoldr :: [Integer] -> Program -- | Sum up a list of Integers using -- --
-- sum = foldl (+) 0 ---- -- This is the canonical space leak in Haskell: note how the accumulator -- is lazy, resulting in a large thunk buildup of suspended additions, -- that is only collapsed to a final value after foldl has -- terminated. The thunks are stored on the heap, so it grows linearly -- with the length of the list. When that thunk is forced, it will push -- lots of additions on the stack; in summary, this produces a heap -- overflow, and if the heap is not exhausted, it will try to overflow -- the stack. sum_foldl :: [Integer] -> Program -- | Sum up a list of Integers using -- --
-- sum = foldr (+) 0 ---- -- Like the foldl version demonstrated in sum_foldl, this -- is a space-leaking implementation of the sum of a list. In this case -- however, the leak spills to the stack and the heap alike: the stack -- contains the continuations for the additions, while the heap contains -- thunks for the recursive call to foldr. sum_foldr :: [Integer] -> Program -- | Calculate the n-th Fibonacci number using the computationally -- (horribly) inefficient formula -- --
-- fib n | n <= 1 = n -- fib n = fib (n-1) + fib (n-2) ---- -- This implementation is stack-only, so enjoy watching it explode. At -- the time of writing this, the machine takes: -- --
-- fib = fib' 0 1 -- where -- fib' x _ | n <= 0 = x -- fib' x !y n = fib' y (x+y) (n-1) ---- -- This implementation is a lot faster than the naive exponential -- implementation. For examle, calculating the 10th Fibonacci number (55) -- takes only 490 steps, compared to the many thousand of the exponential -- version. fibonacciImproved :: Integer -> Program -- | Compute the list of Fibonacci numbers eagerly in the contents, but -- lazy in the spine. -- -- This means that the program will successively generate all the -- Fibonacci numbers, allocating new cells of the infinite list and -- calculating their new values, and garbage collecting previous values. -- -- You can picture this as what happens to fibo in the Haskell -- program -- --
-- main = let fibo = zipWith (+) fibo (tail fibo) -- in traverse_ print fibo --fibonacciZipWith :: Program -- | Force a right-associated concatenation -- --
-- [0] ++ ([1] ++ ([2] ++ ([3]))) ---- -- and store it in the main closure. -- -- This computation is linear in the number of elements of the -- sublists. listConcatRightAssociated :: [[Integer]] -> Program -- | Force a left-associated concatenation -- --
-- (([0] ++ [1]) ++ [2]) ++ [3] ---- -- and store it in the main closure. -- -- This computation is quadratic in the number of elements of the -- sublists. listConcatLeftAssociated :: [[Integer]] -> Program -- | Sort a list with the canonical Quicksort-inspired algorithm often -- found in introductory texts about Haskell. -- -- Note that this is not Quicksort itself, as one key feature of it is -- sorting in-place. In particular, this algorithm is not all that quick, -- as it takes almost a thousand steps to reach the final state when -- sorting [5,4,3,2,1]. naiveSort :: [Integer] -> Program -- | Sort a list with a translation of Haskell's sort, which is an -- implementation of mergesort with ordered sublist detection. librarySort :: [Integer] -> Program -- | This is a naive implementation of the repeat function, -- --
-- repeat x = x : repeat x ---- -- and it is used to compute the infinite repetition of a number. Run -- this program for a couple hundred steps and observe the heap and the -- garbage collector. Count the GC invocations, and compare it to the -- behaviour of repeatSharing! Also note how long it takes to -- generate two successive list elements. -- -- The reason for this behaviour is that the call to repeat -- x is not shared, but done again for each cons cell, requiring one -- heap allocation every time. Cleaning up after this keeps the GC quite -- busy. repeatNaive :: Program -- | This uses a much better definition of repeat, -- --
-- repeat x = let repeatX = x : repeatX -- in repeatX ---- -- This program does only a total of three heap allocations before -- continously running without interruption: one for the -- repeated value, one for the self-referencing cons cell, and -- one beacuse of how forceSpine works. -- -- Note how much smaller the cycles between the traversal of two -- neighbouring list cells is! repeatSharing :: Program