[{"name":"CoreFn.Expr","comment":"\n\n\n## Types\n\n@docs Expr\n@docs Lit, Pat\n\n\n## Constructors\n\nThe following [`Expr`](#Expr) constructors are provided as a convinience for\nexperimenting with the package, and are unlikely to be useful in any serious\napplication as they produce expressions with empty annotations!\n\n@docs app, lam, let_, lit, pat, var, qual, scoped\n\n\n### Literal Constructors\n\n@docs array, list, con, num, obj, rec, str, bool\n\n\n### Pattern Constructors\n\n@docs any, bind, name, val\n\n\n## Queries\n\n@docs annotation\n@docs lambdaBindings, letBindings, patternBindings\n\n\n## Manipulations\n\n@docs transform, transformMany, transformMany_\n@docs fold, foldWithAnnotation, foldWithExpr\n@docs mapAnnotation\n\n\n## JSON\n\n@docs encode, decoder\n\n","unions":[{"name":"Expr","comment":" An expression representing a relatively simple functional programming\nlanguage. It noteably includes pattern matching and let bindings.\n\nThe `ann` type variable represents any annotations you might want to attach to\nthe AST. This could include source spans to locate or translate the AST back to\nsome source code, or it could be type annotations added during type inference,\nor whatever else might be useful!.\n\n","args":["ann"],"cases":[["App",["ann","CoreFn.Expr.Expr ann","CoreFn.Expr.Expr ann"]],["Lam",["ann","String.String","CoreFn.Expr.Expr ann"]],["Let",["ann","String.String","CoreFn.Expr.Expr ann","CoreFn.Expr.Expr ann"]],["Lit",["ann","CoreFn.Expr.Lit (CoreFn.Expr.Expr ann)"]],["Pat",["ann","CoreFn.Expr.Expr ann","List.List ( CoreFn.Expr.Pat ann, Maybe.Maybe (CoreFn.Expr.Expr ann), CoreFn.Expr.Expr ann )"]],["Var",["ann","CoreFn.Name.Name"]]]},{"name":"Lit","comment":" ","args":["expr"],"cases":[["Arr",["List.List expr"]],["Con",["String.String","List.List expr"]],["Int",["Basics.Int"]],["Num",["Basics.Float"]],["Obj",["List.List ( String.String, expr )"]],["Str",["String.String"]]]},{"name":"Pat","comment":" ","args":["ann"],"cases":[["Any",["ann"]],["Bind",["ann","String.String","CoreFn.Expr.Pat ann"]],["Name",["ann","String.String"]],["Val",["ann","CoreFn.Expr.Lit (CoreFn.Expr.Pat ann)"]]]}],"aliases":[],"values":[{"name":"annotation","comment":" Extract the annotation or metadata attached to an expression. This only works\nat a single level. If you want to extract the annotations for subexpressions as\nwell – to convert into a tree for example – take a look at\n[`foldWithAnnotation`](#foldWithAnnotation).\n","type":"CoreFn.Expr.Expr ann -> ann"},{"name":"any","comment":" ","type":"CoreFn.Expr.Pat ()"},{"name":"app","comment":" ","type":"CoreFn.Expr.Expr () -> List.List (CoreFn.Expr.Expr ()) -> CoreFn.Expr.Expr ()"},{"name":"array","comment":" ","type":"List.List expr -> CoreFn.Expr.Lit expr"},{"name":"bind","comment":" ","type":"String.String -> CoreFn.Expr.Pat () -> CoreFn.Expr.Pat ()"},{"name":"bool","comment":" ","type":"Basics.Bool -> CoreFn.Expr.Lit expr"},{"name":"con","comment":" ","type":"String.String -> List.List expr -> CoreFn.Expr.Lit expr"},{"name":"decoder","comment":" ","type":"Json.Decode.Decoder ann -> Json.Decode.Decoder (CoreFn.Expr.Expr ann)"},{"name":"encode","comment":" ","type":"(ann -> Json.Encode.Value) -> CoreFn.Expr.Expr ann -> Json.Encode.Value"},{"name":"fold","comment":" `fold` is an abstraction over a recurisve, bottom-up traversal of an\nexpression. It takes a record of functions, each of which is responsible for\nhandling a particular type of expression but where recursive expressions are\nreplaced with the result of the previous fold. Consider the analog between:\n\n    type Expr ann\n        = App ann (Expr ann) (Expr ann)\n        | Lam ann String (Expr ann)\n        | ...\n\nand\n\n    { onApp : a -> a -> a\n    , onLam : a -> String -> a -> a\n    , ...\n    }\n\nImportantly, the functions we provide to `fold` are **not** recursive!\n\n❓ We mentioned that `fold` performed a _bottom-up_ traversal. You might be\nwondering if it is possible to perform a _top-down_ traversal instead... and it\nis! To achieve this – and bear with me – we need to accumulate a _function_ from\nthe fold, and then execute that.\n\nBy accumulating a function it is possible to pass state _down_ the tree while\nwe build something _up_. This is a bit mind bending so let's take a look at a\nsimple example.\n\n💡 For the true functional programming nerds, this function is also known as a\n**catamorphism** or `cata`.\n\n","type":"{ onApp : a -> a -> a, onLam : String.String -> a -> a, onLet : String.String -> a -> a -> a, onLit : CoreFn.Expr.Lit a -> a, onPat : a -> List.List ( CoreFn.Expr.Pat ann, Maybe.Maybe a, a ) -> a, onVar : CoreFn.Name.Name -> a } -> CoreFn.Expr.Expr ann -> a"},{"name":"foldWithAnnotation","comment":" This is a convenient version of the slightly more general\n[`foldWithExpr`](#foldWithExpr) that only includes the _annotation_ for the\ncurrent expression.\n","type":"{ onApp : ann -> a -> a -> a, onLam : ann -> String.String -> a -> a, onLet : ann -> String.String -> a -> a -> a, onLit : ann -> CoreFn.Expr.Lit a -> a, onPat : ann -> a -> List.List ( CoreFn.Expr.Pat ann, Maybe.Maybe a, a ) -> a, onVar : ann -> CoreFn.Name.Name -> a } -> CoreFn.Expr.Expr ann -> a"},{"name":"foldWithExpr","comment":" Just like how `List.foldl` reduces a list down to a single value, this\nfunction gives us a way to fold an expression tree down to a single value. We\npass in a record of functions that are called according to the type of expression\nwe are currently folding: you can think of it like pattern matching but now how\nthe places where our type would typically recurse on `Expr ann` instead have the\ntype `a` to hold the value of the previous fold.\n\nIn addition, we also get the current `Expr ann` being folded – this can be useful\nif you need the original context of the expression you are folding. If you just\nneed the annotation attached to the expression, you can use\n[`foldWithAnnotation`](#foldWithAnnotation) instead. If you don't need to know\nanything about the expression you are folding, you can use [`fold`](#fold).\n\n💡 For the true functional programming nerds, this function is more commonly\nknown as a **paramorphism** or `para`. Typically described as a model of _primitive\nrecursion_, `para` gives us access to the original expression _as well as_ the\ntransformation that was applied to its child\n\n","type":"{ onApp : CoreFn.Expr.Expr ann -> a -> a -> a, onLam : CoreFn.Expr.Expr ann -> String.String -> a -> a, onLet : CoreFn.Expr.Expr ann -> String.String -> a -> a -> a, onLit : CoreFn.Expr.Expr ann -> CoreFn.Expr.Lit a -> a, onPat : CoreFn.Expr.Expr ann -> a -> List.List ( CoreFn.Expr.Pat ann, Maybe.Maybe a, a ) -> a, onVar : CoreFn.Expr.Expr ann -> CoreFn.Name.Name -> a } -> CoreFn.Expr.Expr ann -> a"},{"name":"lam","comment":" ","type":"List.List String.String -> CoreFn.Expr.Expr () -> CoreFn.Expr.Expr ()"},{"name":"lambdaBindings","comment":" Produces a set of bindings introduced by lambda arguments by walking\nconsecutive `Lam` expressions and accumulating the arguments. For example,\ngiven...\n\n    \\x -> \\y -> \\z -> ...\n\n...we would produce...\n\n    Set.fromList [ \"x\", \"y\", \"z\" ]\n\n...and...\n\n    \\x -> let y = x + 2 in \\z -> ...\n\n...would produce...\n\n    Set.fromList [ \"x\", \"z\" ]\n\n","type":"CoreFn.Expr.Expr ann -> Set.Set String.String"},{"name":"letBindings","comment":" Similar to [`lambdaBindings`](#lambdaBindings), this function produces a set\nof bindings by walking consecutive `Let` expressions and accumulating the names\nintroduced. For example, given...\n\n    let x = 1 in\n    let y = 2 in\n    let z = 3 in\n    ...\n\n...we would produce...\n\n        Set.fromList [ \"x\", \"y\", \"z\" ]\n\n","type":"CoreFn.Expr.Expr ann -> Set.Set String.String"},{"name":"let_","comment":" ","type":"List.List ( String.String, CoreFn.Expr.Expr () ) -> CoreFn.Expr.Expr () -> CoreFn.Expr.Expr ()"},{"name":"list","comment":" ","type":"List.List expr -> CoreFn.Expr.Lit expr"},{"name":"lit","comment":" ","type":"CoreFn.Expr.Lit (CoreFn.Expr.Expr ()) -> CoreFn.Expr.Expr ()"},{"name":"mapAnnotation","comment":" ","type":"(a -> b) -> CoreFn.Expr.Expr a -> CoreFn.Expr.Expr b"},{"name":"name","comment":" ","type":"String.String -> CoreFn.Expr.Pat ()"},{"name":"num","comment":" ","type":"Basics.Float -> CoreFn.Expr.Lit expr"},{"name":"obj","comment":" ","type":"List.List ( String.String, expr ) -> CoreFn.Expr.Lit expr"},{"name":"pat","comment":" ","type":"CoreFn.Expr.Expr () -> List.List ( CoreFn.Expr.Pat (), Maybe.Maybe (CoreFn.Expr.Expr ()), CoreFn.Expr.Expr () ) -> CoreFn.Expr.Expr ()"},{"name":"patternBindings","comment":" Pattern matching can introduce new bindings into scope the same way lambda\nand let expressions might. Not all patterns introduce bindings, though, so this\nfunction tells you what – if any – are introduced!\n\nFor example, given...\n\n    [ x, 2, z ] ->\n        ...\n\n...we would produce...\n\n    Set.fromList [ \"x\", \"z\" ]\n\n...and...\n\n    ( _, { y } ) ->\n        ...\n\n...would produce...\n\n    Set.fromList [ \"y\" ]\n\n","type":"CoreFn.Expr.Pat ann -> Set.Set String.String"},{"name":"qual","comment":" ","type":"String.String -> CoreFn.Name.Name -> CoreFn.Expr.Expr ()"},{"name":"rec","comment":" ","type":"List.List ( String.String, expr ) -> CoreFn.Expr.Lit expr"},{"name":"scoped","comment":" ","type":"List.List String.String -> CoreFn.Name.Name -> CoreFn.Expr.Expr ()"},{"name":"str","comment":" ","type":"String.String -> CoreFn.Expr.Lit expr"},{"name":"transform","comment":" Recursively transform an expression, bottom-up.\n","type":"(CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann) -> CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann"},{"name":"transformMany","comment":" Like [`transform`](#transform), this recursively transforms an expression from\nthe bottom up. It's behaviour is different in two important ways:\n\n  - We supply a _list_ of transformations, that are applied in sequence.\n  - Transformations are **continuously applied** until the result does not change.\n\nTransformations are applied to sub-expressions. If you want a non-recursive version\nof this function, check out [`transformMany_`](#transformMany_).\n\n🚨 Be mindful of what transformations you are applying, and in what order you\nsupply them. It is possible to overflow the stack with `transformMany` if the\ntransformations you supply diverge – we will never stop trying to apply them!\n\n","type":"List.List (CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann) -> CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann"},{"name":"transformMany_","comment":" Repeatedly apply a list of transformations to a given expression. This is\ndistinct from [`transformMany`](#transformMany) in that it does **not** apply the\ntransformations recursively to sub-expressions.\n\n🚨 Be mindful of what transformations you are applying, and in what order you\nsupply them. It is possible to overflow the stack with `transformMany_` if the\ntransformations you supply diverge – we will never stop trying to apply them!\n\n","type":"List.List (CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann) -> CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann"},{"name":"val","comment":" ","type":"CoreFn.Expr.Lit (CoreFn.Expr.Pat ()) -> CoreFn.Expr.Pat ()"},{"name":"var","comment":" ","type":"String.String -> CoreFn.Expr.Expr ()"}],"binops":[]},{"name":"CoreFn.Name","comment":"\n\n\n## Types\n\n@docs Name\n\n\n## Constructors\n\n@docs scoped\n\n\n## Conversions\n\n@docs toString, lowerString, upperString, synthString\n\n\n## JSON\n\n@docs encode, decoder\n\n","unions":[{"name":"Name","comment":" ","args":[],"cases":[["Lower",["String.String"]],["Upper",["String.String"]],["Synth",["Basics.Int"]],["Qualified",["String.String","CoreFn.Name.Name"]]]}],"aliases":[],"values":[{"name":"decoder","comment":" ","type":"Json.Decode.Decoder CoreFn.Name.Name"},{"name":"encode","comment":" ","type":"CoreFn.Name.Name -> Json.Encode.Value"},{"name":"lowerString","comment":" ","type":"CoreFn.Name.Name -> Maybe.Maybe String.String"},{"name":"scoped","comment":" ","type":"List.List String.String -> CoreFn.Name.Name -> CoreFn.Name.Name"},{"name":"synthString","comment":" ","type":"CoreFn.Name.Name -> Maybe.Maybe String.String"},{"name":"toString","comment":" ","type":"String.String -> CoreFn.Name.Name -> String.String"},{"name":"upperString","comment":" ","type":"CoreFn.Name.Name -> Maybe.Maybe String.String"}],"binops":[]},{"name":"CoreFn.Optimise.ConstFold","comment":"\n\n@docs common, custom\n\n\n## Operators\n\n@docs unop, binop\n\n\n### Typed Operators\n\n@docs intUnop, numUnop, strUnop\n@docs intBinop, numBinop, strBinop\n\n\n## Functions\n\nThe following collection of functions reduce some of the boilerplate when\noptimising for n-arity functions. Because the `CoreFn` expression models\nfunction application as repeaded application of single-argument functions, there\nends up being quite a bit of nesting if you want to pull out 3, 4, ..8 arguments!\n\n@docs f, f2, f3, f4, f5, f6, f7, f8\n\n","unions":[],"aliases":[],"values":[{"name":"binop","comment":" Just like [`unop`](#unop), we can eliminate a binary operator applied to two\nliteral values with this function. You can probably guess how to implement\nsomething like addition (there are [even](#numBinop) [helpers](#intBinop) to make\nthat easier) so let's look at a different example.\n\nWe could eliminate object/record access like so:\n\n    import CoreFn.Expr as Expr exposing (Expr)\n    import CoreFn.Name as Name\n    import CoreFn.Optimise.ConstFold as ConstFold\n\n    access : Expr -> Maybe Expr\n    access =\n        ConstFold.binop\n            (Name.Lower \"access\")\n            (\\lhs rhs ->\n                case ( lhs, rhs ) of\n                    ( Expr.Str key, Expr.Obj obj ) ->\n                        List.filter (Tuple.first >> (==) key) obj\n                            |> List.head\n                            |> Maybe.map Tuple.second\n\n                    _ ->\n                        Nothing\n            )\n\nSuch that if we're given...\n\n    { foo = 1 }.foo\n\n...we can eliminate the whole thing to...\n\n    1\n\n","type":"CoreFn.Name.Name -> (ann -> ann -> ann) -> (CoreFn.Expr.Lit (CoreFn.Expr.Expr ann) -> CoreFn.Expr.Lit (CoreFn.Expr.Expr ann) -> Maybe.Maybe (CoreFn.Expr.Lit (CoreFn.Expr.Expr ann))) -> CoreFn.Expr.Expr ann -> Maybe.Maybe (CoreFn.Expr.Expr ann)"},{"name":"common","comment":" A convenient helper to eliminate common maths expressions and other operators.\nLike all the optimisations in this module this will only eliminate expressions\nthat only contain literals, but when combined with the constant propagation\nhelpers defined in [`ConstProp`](./CoreFn-Optimise-ConstProp) you can eliminate\nconstant variables too.\n\nThis optimisation is applied bottom-up, so it will eliminate compound expressions\nlike `1 + 2 * 3` (assuming you provide names for your `add` and `mul` operators).\n\n","type":"{ add : Maybe.Maybe CoreFn.Name.Name, sub : Maybe.Maybe CoreFn.Name.Name, mul : Maybe.Maybe CoreFn.Name.Name, div : Maybe.Maybe CoreFn.Name.Name, neg : Maybe.Maybe CoreFn.Name.Name } -> (ann -> ann -> ann) -> CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann"},{"name":"custom","comment":" Allows you to supply a list of custom eliminations that may or may not\nsucceed. Best used in combination with the helpers defined elsewhere in this\nmodule like [`unop`](#unop), [`binop`](#binop), [`fn`](#fn), and so on.\n","type":"List.List (CoreFn.Expr.Expr ann -> Maybe.Maybe (CoreFn.Expr.Expr ann)) -> CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann"},{"name":"f","comment":" ","type":"CoreFn.Name.Name -> (CoreFn.Expr.Expr ann -> Maybe.Maybe (CoreFn.Expr.Expr ann)) -> CoreFn.Expr.Expr ann -> Maybe.Maybe (CoreFn.Expr.Expr ann)"},{"name":"f2","comment":" ","type":"CoreFn.Name.Name -> (CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann -> Maybe.Maybe (CoreFn.Expr.Expr ann)) -> CoreFn.Expr.Expr ann -> Maybe.Maybe (CoreFn.Expr.Expr ann)"},{"name":"f3","comment":" ","type":"CoreFn.Name.Name -> (CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann -> Maybe.Maybe (CoreFn.Expr.Expr ann)) -> CoreFn.Expr.Expr ann -> Maybe.Maybe (CoreFn.Expr.Expr ann)"},{"name":"f4","comment":" ","type":"CoreFn.Name.Name -> (CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann -> Maybe.Maybe (CoreFn.Expr.Expr ann)) -> CoreFn.Expr.Expr ann -> Maybe.Maybe (CoreFn.Expr.Expr ann)"},{"name":"f5","comment":" ","type":"CoreFn.Name.Name -> (CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann -> Maybe.Maybe (CoreFn.Expr.Expr ann)) -> CoreFn.Expr.Expr ann -> Maybe.Maybe (CoreFn.Expr.Expr ann)"},{"name":"f6","comment":" ","type":"CoreFn.Name.Name -> (CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann -> Maybe.Maybe (CoreFn.Expr.Expr ann)) -> CoreFn.Expr.Expr ann -> Maybe.Maybe (CoreFn.Expr.Expr ann)"},{"name":"f7","comment":" ","type":"CoreFn.Name.Name -> (CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann -> Maybe.Maybe (CoreFn.Expr.Expr ann)) -> CoreFn.Expr.Expr ann -> Maybe.Maybe (CoreFn.Expr.Expr ann)"},{"name":"f8","comment":" ","type":"CoreFn.Name.Name -> (CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann -> Maybe.Maybe (CoreFn.Expr.Expr ann)) -> CoreFn.Expr.Expr ann -> Maybe.Maybe (CoreFn.Expr.Expr ann)"},{"name":"intBinop","comment":" ","type":"CoreFn.Name.Name -> (ann -> ann -> ann) -> (Basics.Int -> Basics.Int -> Basics.Int) -> CoreFn.Expr.Expr ann -> Maybe.Maybe (CoreFn.Expr.Expr ann)"},{"name":"intUnop","comment":" ","type":"CoreFn.Name.Name -> (Basics.Int -> Basics.Int) -> CoreFn.Expr.Expr ann -> Maybe.Maybe (CoreFn.Expr.Expr ann)"},{"name":"numBinop","comment":" ","type":"CoreFn.Name.Name -> (ann -> ann -> ann) -> (Basics.Float -> Basics.Float -> Basics.Float) -> CoreFn.Expr.Expr ann -> Maybe.Maybe (CoreFn.Expr.Expr ann)"},{"name":"numUnop","comment":" ","type":"CoreFn.Name.Name -> (Basics.Float -> Basics.Float) -> CoreFn.Expr.Expr ann -> Maybe.Maybe (CoreFn.Expr.Expr ann)"},{"name":"strBinop","comment":" ","type":"CoreFn.Name.Name -> (ann -> ann -> ann) -> (String.String -> String.String -> String.String) -> CoreFn.Expr.Expr ann -> Maybe.Maybe (CoreFn.Expr.Expr ann)"},{"name":"strUnop","comment":" ","type":"CoreFn.Name.Name -> (String.String -> String.String) -> CoreFn.Expr.Expr ann -> Maybe.Maybe (CoreFn.Expr.Expr ann)"},{"name":"unop","comment":" Eliminate a unary operator applied to some literal. We could implement an\nelimination for simple negation like so:\n\n    import CoreFn.Expr as Expr exposing (Expr)\n    import CoreFn.Name as Name\n    import CoreFn.Optimise.ConstFold as ConstFold\n\n    negate : Expr -> Maybe Expr\n    negate =\n        ConstFold.unop\n            (Name.Lower \"negate\")\n            (\\lit ->\n                case lit of\n                    Expr.Int int ->\n                        Just <| Expr.Int <| Basics.negate int\n\n                    Expr.Num num ->\n                        Just <| Expr.Num <| Basics.negate num\n\n                    _ ->\n                        Nothing\n            )\n\n","type":"CoreFn.Name.Name -> (CoreFn.Expr.Lit (CoreFn.Expr.Expr ann) -> Maybe.Maybe (CoreFn.Expr.Lit (CoreFn.Expr.Expr ann))) -> CoreFn.Expr.Expr ann -> Maybe.Maybe (CoreFn.Expr.Expr ann)"}],"binops":[]},{"name":"CoreFn.Optimise.ConstProp","comment":"\n\n@docs literals\n@docs custom\n\n","unions":[],"aliases":[],"values":[{"name":"custom","comment":" ","type":"(CoreFn.Expr.Expr ann -> Basics.Bool) -> CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann"},{"name":"literals","comment":" ","type":"CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann"}],"binops":[]},{"name":"CoreFn.Optimise.DeadCode","comment":"\n\n@docs conservative, aggressive\n@docs custom\n\n","unions":[],"aliases":[],"values":[{"name":"aggressive","comment":" ","type":"CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann"},{"name":"conservative","comment":" ","type":"List.List CoreFn.Name.Name -> CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann"},{"name":"custom","comment":" ","type":"(CoreFn.Name.Name -> Maybe.Maybe String.String) -> (CoreFn.Expr.Expr ann -> Basics.Bool) -> CoreFn.Expr.Expr ann -> CoreFn.Expr.Expr ann"}],"binops":[]}]