h$8       !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~                                                               (c) 2019-2021 Rudy Matela$3-Clause BSD (see the file LICENSE) Rudy Matela  Safe-Inferred Iexpress O(n log n)0. Sorts and remove repetitions. Equivalent to  nub . sort. > nubSort [1,2,3] [1,2,3] > nubSort [3,2,1] [1,2,3] > nubSort [3,2,1,3,2,1] [1,2,3] > nubSort [3,3,1,1,2,2] [1,2,3]express O(n log n). Checks that all elements of the first list are elements of the second.express O(n log n). Checks that all elements of the first list are elements of the second.express O(n log n). Checks that all elements are unique. This function is a faster equivalent to the following: isNub xs = nub xs == xs Examples: isNub [] = True isNub [1,2,3] = True isNub [2,1,2] = FalseexpressO(n). Like 0 but returns the key itself if nothing is found. > lookupId 5 [(1,2),(3,4)] 5 "> lookupId 5 [(1,2),(3,4),(5,6)] 65(c) 2016-2021 Rudy Matela$3-Clause BSD (see the file LICENSE) Rudy Matela  Safe-InferredexpressUnquotes a string if possible, otherwise, this is just an identity. > unquote "\"string\"" "string" > unquote "something else" "something else"express8Checks if a string-encoded Haskell expression is atomic. > atomic "123" True > atomic "42 + 1337" False > atomic "'a'" True > atomic "[1,2,3,4,5]" True > atomic "(1,2,3,4,5)" True>FIXME: The current implementation may produce false positives: > atomic "'a' < 'b'" True > atomic "\"asdf\" ++ \"qwer\"" True > atomic "[1,2,3] ++ [4,5,6]" True7but this does not cause problems for (all?) most cases. express'Check if a function / operator is infix isInfix "foo" == False isInfix "(+)" == False isInfix "`foo`" == True isInfix "+" == True express3Returns the precedence of default Haskell operatorsexpressIs the string of the form `string`express3Transform an infix operator into an infix function: 3toPrefix "`foo`" == "foo" toPrefix "+" == "(+)"expressReturns an infinite list of variable names based on the given template. > variableNamesFromTemplate "x" ["x", "y", "z", "x'", "y'", ...] > variableNamesFromTemplate "p" ["p", "q", "r", "p'", "q'", ...] > variableNamesFromTemplate "xy" ["xy", "zw", "xy'", "zw'", "xy''", ...]    (c) 2019-2021 Rudy Matela$3-Clause BSD (see the file LICENSE) Rudy Matela  Safe-InferredYexpressIf we were to come up with a variable name for the given type what  would it be?An instance for a given type  Ty  is simply given by: #instance Name Ty where name _ = "x" Examples: > name (undefined :: Int) "x" > name (undefined :: Bool) "p"  > name (undefined :: [Int]) "xs";This is then used to generate an infinite list of variable : > names (undefined :: Int) ["x", "y", "z", "x'", "y'", "z'", "x''", "y''", "z''", ...] > names (undefined :: Bool) ["p", "q", "r", "p'", "q'", "r'", "p''", "q''", "r''", ...] > names (undefined :: [Int]) ["xs", "ys", "zs", "xs'", "ys'", "zs'", "xs''", "ys''", ...]expressO(1).;Returns a name for a variable of the given argument's type. > name (undefined :: Int) "x" !> name (undefined :: [Bool]) "ps" +> name (undefined :: [Maybe Integer]) "mxs"The default definition is:  name _ = "x"expressReturns na infinite list of variable names from the given type: the result of  after . > names (undefined :: Int) ["x", "y", "z", "x'", "y'", "z'", "x''", "y''", "z''", ...] > names (undefined :: Bool) ["p", "q", "r", "p'", "q'", "r'", "p''", "q''", "r''", ...] > names (undefined :: [Int]) ["xs", "ys", "zs", "xs'", "ys'", "zs'", "xs''", "ys''", ...]express names (undefined :: [Int]) = ["xs", "ys", "zs", "xs'", ...] names (undefined :: [Bool]) = ["ps", "qs", "rs", "ps'", ...]express names (undefined :: ((),(),(),())) = ["uuuu", "uuuu1", ...] names (undefined :: (Int,Int,Int,Int)) = ["xxxx", ...] express names (undefined :: (Int,Int,Int)) = ["xyz","uvw", ...] names (undefined :: (Int,Bool,Char)) = ["xpc", "xpc1", ...]!express names (undefined :: (Int,Int)) = ["xy", "zw", "xy'", ...] names (undefined :: (Bool,Bool)) = ["pq", "rs", "pq'", ...]"express names (undefined :: Either Int Int) = ["exy", "exy1", ...] names (undefined :: Either Int Bool) = ["exp", "exp1", ...]#express names (undefined :: Maybe Int) = ["mx", "mx1", "mx2", ...] nemes (undefined :: Maybe Bool) = ["mp", "mp1", "mp2", ...]$express names (undefined :: ()->()) = ["f", "g", "h", "f'", ...] names (undefined :: Int->Int) = ["f", "g", "h", ...]%express name (undefined :: Double) = "x" names (undefined :: Double) = ["x", "y", "z", "x'", ...]&express name (undefined :: Float) = "x" names (undefined :: Float) = ["x", "y", "z", "x'", ...]'express name (undefined :: Rational) = "q" names (undefined :: Rational) = ["q", "r", "s", "q'", ...](express name (undefined :: Ordering) = "o" names (undefined :: Ordering) = ["o", "p", "q", "o'", ...])express name (undefined :: Char) = "c" names (undefined :: Char) = ["c", "d", "e", "c'", "d'", ...]*express name (undefined :: Integer) = "x" names (undefined :: Integer) = ["x", "y", "z", "x'", ...]+express name (undefined :: Int) = "x" names (undefined :: Int) = ["x", "y", "z", "x'", "y'", ...],express name (undefined :: Bool) = "p" names (undefined :: Bool) = ["p", "q", "r", "p'", "q'", ...]-express name (undefined :: ()) = "u" names (undefined :: ()) = ["u", "v", "w", "u'", "v'", ...](c) 2019-2021 Rudy Matela$3-Clause BSD (see the file LICENSE) Rudy Matela None A9expressGiven a type name, return the number of arguments taken by that type. Examples in partially broken TH: arity ''Int === Q 0 arity ''Int->Int === Q 0 arity ''Maybe === Q 1 arity ''Either === Q 2 arity ''Int-> === Q 1This works for Data's and Newtype's and it is useful when generating typeclass instances. ./0123456789:;<=>?@ABC1./23456789:;A(c) 2019-2021 Rudy Matela$3-Clause BSD (see the file LICENSE) Rudy Matela None'Dexpress Derives a  instance for the given type .This function needs the TemplateHaskell extension.EexpressSame as D4 but does not warn when instance already exists (D is preferable).Fexpress Derives a  instance for a given type 3 cascading derivation of type arguments as well.DEFDFE(c) 2016-2021 Rudy Matela$3-Clause BSD (see the file LICENSE) Rudy Matela  Safe-Inferred,MexpressThis function returns the type of the element of a list. It will throw an error when not given the list type. > > elementTy $ typeOf (undefined :: [Int]) Int > > elementTy $ typeOf (undefined :: [[Int]]) [Int] > > elementTy $ typeOf (undefined :: [Bool]) Bool > > elementTy $ typeOf (undefined :: Bool) *** Exception: error (elementTy): `Bool' is not a list typeUexpressO(n)9. Return all sub types of a given type including itself. +> typesIn $ typeOf (undefined :: Int) [Int] -> typesIn $ typeOf (undefined :: Bool) [Bool] 7> typesIn $ typeOf (undefined :: [Int]) [ Int , [Int] ] > typesIn $ typeOf (undefined :: Int -> Int -> Int) [ Int , Int -> Int , Int -> Int -> Int ] > typesIn $ typeOf (undefined :: Int -> [Int] -> [Int]) [ Int , [Int] , [Int] -> [Int] , Int -> [Int] -> [Int] ] > typesIn $ typeOf (undefined :: Maybe Bool) [ Bool , Maybe Bool ]WexpressAn infix alias for  . It is right associative.5 GHIJKLMNOPQRSTUVWHJRKLINOPSTQGMUVWW9 (c) 2019-2021 Rudy Matela$3-Clause BSD (see the file LICENSE) Rudy Matela  Safe-Inferred3s+XexpressValues of type X represent objects or applications between objects. Each object is encapsulated together with its type and string representation. Values encoded in Xs are always monomorphic.An X can be constructed using:\, for values that are   instances;[, for values that are not   instances, like functions;Z, for applications between Xs. > val False False :: Bool 0> value "not" not :$ val False not False :: BoolAn X can be evaluated using e, f or g. > evl $ val (1 :: Int) :: Int 1 1> evaluate $ val (1 :: Int) :: Maybe Bool Nothing > eval 'a' (val 'b') 'b' ing a value of type X will return a pretty-printed representation of the expression together with its type. 9> show (value "not" not :$ val False) "not False :: Bool"X is like  2 but has support for applications and variables (Z, ^).The ^ underscore convention: Functions that manipulate X)s usually follow the convention where a [ whose  representation starts with '_' represents a ^iable.Yexpressa [ enconded as  and  Zexpress(function application between expressions[expressO(1). It takes a string representation of a value and a value, returning an X- with that terminal value. For instances of  , it is preferable to use \. '> value "0" (0 :: Integer) 0 :: Integer > value "'a'" 'a' 'a' :: Char  > value "True" True True :: Bool 0> value "id" (id :: Int -> Int) id :: Int -> Int > value "(+)" ((+) :: Int -> Int -> Int) (+) :: Int -> Int -> Int > value "sort" (sort :: [Bool] -> [Bool]) sort :: [Bool] -> [Bool]\expressO(1). A shorthand for [ for values that are   instances. > val (0 :: Int) 0 :: Int > val 'a' 'a' :: Char > val True True :: BoolExample equivalences to [: val 0 = value "0" 0 val 'a' = value "'a'" 'a' val True = value "True" True]expressO(n). Creates an X' representing a function application.   an X! application if the types match,   otherwise. (cf. Z) :> value "id" (id :: () -> ()) $$ val () Just (id () :: ()) > value "abs" (abs :: Int -> Int) $$ val (1337 :: Int) Just (abs 1337 :: Int) 4> value "abs" (abs :: Int -> Int) $$ val 'a' Nothing 3> value "abs" (abs :: Int -> Int) $$ val () Nothing^expressO(1). Creates an X representing a variable with the given name and argument type. %> var "x" (undefined :: Int) x :: Int #> var "u" (undefined :: ()) u :: () +> var "xs" (undefined :: [Int]) xs :: [Int]This function follows the underscore convention: a variable is just a [6 whose string representation starts with underscore ('_')._expressO(n). Computes the type of an expression. This raises errors, but this should not happen if expressions are smart-constructed with ]. > let one = val (1 :: Int) > let bee = val 'b' > let absE = value "abs" (abs :: Int -> Int)  > typ one Int > typ bee Char > typ absE Int -> Int > typ (absE :$ one) Int > typ (absE :$ bee) *** Exception: type mismatch, cannot apply `Int -> Int' to `Char' > typ ((absE :$ bee) :$ one) *** Exception: type mismatch, cannot apply `Int -> Int' to `Char'`expressO(n). Computes the type of an expression returning either the type of the given expression when possible or when there is a type error, the pair of types which produced the error. > let one = val (1 :: Int) > let bee = val 'b' > let absE = value "abs" (abs :: Int -> Int) > etyp one Right Int > etyp bee Right Char > etyp absE Right (Int -> Int) > etyp (absE :$ one) Right Int ,> etyp (absE :$ bee) Left (Int -> Int, Char) 5> etyp ((absE :$ bee) :$ one) Left (Int -> Int, Char)aexpressO(n) . Returns   the type of an expression or   when there is an error. > let one = val (1 :: Int) > let bee = val 'b' > let absE = value "abs" (abs :: Int -> Int) > mtyp one Just Int > mtyp (absE :$ bee) NothingbexpressO(n). Returns whether the given X is ill typed. (cf. c) > let one = val (1 :: Int) > let bee = val 'b' > let absE = value "abs" (abs :: Int -> Int) +> isIllTyped (absE :$ val (1 :: Int)) False #> isIllTyped (absE :$ val 'b') TruecexpressO(n). Returns whether the given X is well typed. (cf. b) +> isWellTyped (absE :$ val (1 :: Int)) True %> isWellTyped (absE :$ val 'b') FalsedexpressO(n). Returns whether the given X? is of a functional type. This is the same as checking if the ~ of the given X is non-zero. .> isFun (value "abs" (abs :: Int -> Int)) True > isFun (val (1::Int)) False > isFun (value "const" (const :: Bool -> Bool -> Bool) :$ val False) TrueeexpressO(n).  ; the value of an expression when possible (correct type),  - otherwise. This does not catch errors from     [s. > let one = val (1 :: Int) > let bee = val 'b' > let negateE = value "negate" (negate :: Int -> Int) "> evaluate one :: Maybe Int Just 1 $> evaluate one :: Maybe Char Nothing #> evaluate bee :: Maybe Int Nothing %> evaluate bee :: Maybe Char Just 'b' 2> evaluate $ negateE :$ one :: Maybe Int Just (-1) 0> evaluate $ negateE :$ bee :: Maybe Int NothingfexpressO(n). Evaluates an expression when possible (correct type). Returns a default value otherwise. > let two = val (2 :: Int) > let three = val (3 :: Int) > let e1 -+- e2 = value "+" ((+) :: Int->Int->Int) :$ e1 :$ e2 !> eval 0 $ two -+- three :: Int 5 &> eval 'z' $ two -+- three :: Char 'z' #> eval 0 $ two -+- val '3' :: Int 0gexpressO(n). Evaluates an expression when possible (correct type). Raises an error otherwise. > evl $ two -+- three :: Int 5 > evl $ two -+- three :: Bool *** Exception: evl: cannot evaluate Expr `2 + 3 :: Int' at the Bool type-This may raise errors, please consider using f or e.hexpressO(n)). Evaluates an expression to a terminal   value when possible. Returns   otherwise. <> toDynamic $ val (123 :: Int) :: Maybe Dynamic Just <> > toDynamic $ value "abs" (abs :: Int -> Int) :$ val (-1 :: Int) Just <> > toDynamic $ value "abs" (abs :: Int -> Int) :$ val 'a' NothingkexpressO(n). Returns a string representation of an expression. Differently from   (:: Expr -> String9) this function does not include the type in the output. )> putStrLn $ showExpr (one -+- two) 1 + 2 > putStrLn $ showExpr $ (pp -||- true) -&&- (qq -||- false) (p || True) && (q || False)lexpressO(n)". Compares the complexity of two Xs. An expression e1 is strictly simpler than another expression e2 if the first of the following conditions to distingish between them is: e1 is smaller in size/length than e2 , e.g.: x + y < x + (y + z);or, e1" has more distinct variables than e2 , e.g.:  x + y < x + x;or, e1$ has more variable occurrences than e2 , e.g.:  x + x < 1 + x;or, e1# has fewer distinct constants than e2 , e.g.:  1 + 1 < 0 + 1.9They're otherwise considered of equal complexity, e.g.: x + y and y + z. 9> (xx -+- yy) `compareComplexity` (xx -+- (yy -+- zz)) LT 0> (xx -+- yy) `compareComplexity` (xx -+- xx) LT 1> (xx -+- xx) `compareComplexity` (one -+- xx) LT 5> (one -+- one) `compareComplexity` (zero -+- one) LT 0> (xx -+- yy) `compareComplexity` (yy -+- zz) EQ 6> (zero -+- one) `compareComplexity` (one -+- zero) EQ%This comparison is not a total order.mexpressO(n).+ Lexicographical structural comparison of Xs where variables < constants < applications then types are compared before string representations. > compareLexicographically one (one -+- one) LT > compareLexicographically one zero GT > compareLexicographically (xx -+- zero) (zero -+- xx) LT > compareLexicographically (zero -+- xx) (zero -+- xx) EQ(cf. G)!This comparison is a total order.nexpressO(n). A fast total order between X!s that can be used when sorting X values.&This is lazier than its counterparts l and m" and tries to evaluate the given Xs as least as possible.oexpressO(n)!. Unfold a function application X( into a list of function and arguments. unfoldApp $ e0 = [e0] unfoldApp $ e0 :$ e1 = [e0,e1] unfoldApp $ e0 :$ e1 :$ e2 = [e0,e1,e2] unfoldApp $ e0 :$ e1 :$ e2 :$ e3 = [e0,e1,e2,e3] Remember Z is left-associative, so: unfoldApp e0 = [e0] unfoldApp (e0 :$ e1) = [e0,e1] unfoldApp ((e0 :$ e1) :$ e2) = [e0,e1,e2] unfoldApp (((e0 :$ e1) :$ e2) :$ e3) = [e0,e1,e2,e3]pexpressO(n). Check if an X3 has a variable. (By convention, any value whose  representation starts with '_'.) ,> hasVar $ value "not" not :$ val True False > hasVar $ value "&&" (&&) :$ var "p" (undefined :: Bool) :$ val True TrueqexpressO(n). Returns whether a X has no$ variables. This is equivalent to " not . hasVar".,The name "ground" comes from term rewriting. -> isGround $ value "not" not :$ val True True > isGround $ value "&&" (&&) :$ var "p" (undefined :: Bool) :$ val True FalserexpressO(1). Returns whether an X is a terminal constant. (cf. q). ,> isConst $ var "x" (undefined :: Int) False > isConst $ val False True .> isConst $ value "not" not :$ val False FalsesexpressO(1). Returns whether an X is a terminal variable (^ ). (cf. p). )> isVar $ var "x" (undefined :: Int) True > isVar $ val False False >> isVar $ value "not" not :$ var "p" (undefined :: Bool) FalsetexpressO(1). Returns whether an X is a terminal value (Y). +> isValue $ var "x" (undefined :: Int) True > isValue $ val False True > isValue $ value "not" not :$ var "p" (undefined :: Bool) False+This is equivalent to pattern matching the Y constructor. Properties:  isValue (Value e) = True  isValue (e1 :$ e2) = False  isValue = not . isApp # isValue e = isVar e || isConst euexpressO(1). Returns whether an X is an application (Z). *> isApp $ var "x" (undefined :: Int) False > isApp $ val False False => isApp $ value "not" not :$ var "p" (undefined :: Bool) True+This is equivalent to pattern matching the Z constructor. Properties:  isApp (e1 :$ e2) = True  isApp (Value e) = False  isApp = not . isValue - isApp e = not (isVar e) && not (isConst e)vexpressO(n) for the spine, O(n^2) for full evaluation. Lists subexpressions of a given expression in order and with repetitions. This includes the expression itself and partial function applications. (cf. w) > subexprs (xx -+- yy) [ x + y :: Int , (x +) :: Int -> Int , (+) :: Int -> Int -> Int , x :: Int , y :: Int ] > subexprs (pp -&&- (pp -&&- true)) [ p && (p && True) :: Bool , (p &&) :: Bool -> Bool , (&&) :: Bool -> Bool -> Bool , p :: Bool , p && True :: Bool , (p &&) :: Bool -> Bool , (&&) :: Bool -> Bool -> Bool , p :: Bool , True :: Bool ]wexpressO(n^3) for full evaluation. Lists all subexpressions of a given expression without repetitions. This includes the expression itself and partial function applications. (cf. v) > nubSubexprs (xx -+- yy) [ x :: Int , y :: Int , (+) :: Int -> Int -> Int , (x +) :: Int -> Int , x + y :: Int ] > nubSubexprs (pp -&&- (pp -&&- true)) [ p :: Bool , True :: Bool , (&&) :: Bool -> Bool -> Bool , (p &&) :: Bool -> Bool , p && True :: Bool , p && (p && True) :: Bool ]Runtime averages to  O(n^2 log n), on evenly distributed expressions such as (f x + g y) + (h z + f w) ; and to O(n^3) on deep expressions such as f (g (h (f (g (h x))))).xexpressO(n). Lists all terminal values in an expression in order and with repetitions. (cf. y) > values (xx -+- yy) [ (+) :: Int -> Int -> Int , x :: Int , y :: Int ] > values (xx -+- (yy -+- zz)) [ (+) :: Int -> Int -> Int , x :: Int , (+) :: Int -> Int -> Int , y :: Int , z :: Int ] > values (zero -+- (one -*- two)) [ (+) :: Int -> Int -> Int , 0 :: Int , (*) :: Int -> Int -> Int , 1 :: Int , 2 :: Int ] > values (pp -&&- true) [ (&&) :: Bool -> Bool -> Bool , p :: Bool , True :: Bool ]yexpressO(n^2). Lists all terminal values in an expression without repetitions. (cf. x) > nubValues (xx -+- yy) [ x :: Int , y :: Int , (+) :: Int -> Int -> Int] > nubValues (xx -+- (yy -+- zz)) [ x :: Int , y :: Int , z :: Int , (+) :: Int -> Int -> Int ] > nubValues (zero -+- (one -*- two)) [ 0 :: Int , 1 :: Int , 2 :: Int , (*) :: Int -> Int -> Int , (+) :: Int -> Int -> Int ] > nubValues (pp -&&- pp) [ p :: Bool , (&&) :: Bool -> Bool -> Bool ]Runtime averages to  O(n log n), on evenly distributed expressions such as (f x + g y) + (h z + f w) ; and to O(n^2) on deep expressions such as f (g (h (f (g (h x))))).zexpressO(n). List terminal constants in an expression in order and with repetitions. (cf. {) 1> consts (xx -+- yy) [ (+) :: Int -> Int -> Int ] > consts (xx -+- (yy -+- zz)) [ (+) :: Int -> Int -> Int , (+) :: Int -> Int -> Int ] > consts (zero -+- (one -*- two)) [ (+) :: Int -> Int -> Int , 0 :: Int , (*) :: Int -> Int -> Int , 1 :: Int , 2 :: Int ] > consts (pp -&&- true) [ (&&) :: Bool -> Bool -> Bool , True :: Bool ]{expressO(n^2). List terminal constants in an expression without repetitions. (cf. z) 4> nubConsts (xx -+- yy) [ (+) :: Int -> Int -> Int ] => nubConsts (xx -+- (yy -+- zz)) [ (+) :: Int -> Int -> Int ] > nubConsts (pp -&&- true) [ True :: Bool , (&&) :: Bool -> Bool -> Bool ]Runtime averages to  O(n log n), on evenly distributed expressions such as (f x + g y) + (h z + f w) ; and to O(n^2) on deep expressions such as f (g (h (f (g (h x))))).|expressO(n). Lists all variables in an expression in order and with repetitions. (cf. }) *> vars (xx -+- yy) [ x :: Int , y :: Int ] >> vars (xx -+- (yy -+- xx)) [ x :: Int , y :: Int , x :: Int ] "> vars (zero -+- (one -*- two)) [] !> vars (pp -&&- true) [p :: Bool]}expressO(n^2). Lists all variables in an expression without repetitions. (cf. |) -> nubVars (yy -+- xx) [ x :: Int , y :: Int ] 6> nubVars (xx -+- (yy -+- xx)) [ x :: Int , y :: Int ] %> nubVars (zero -+- (one -*- two)) [] $> nubVars (pp -&&- true) [p :: Bool]Runtime averages to  O(n log n), on evenly distributed expressions such as (f x + g y) + (h z + f w) ; and to O(n^2) on deep expressions such as f (g (h (f (g (h x))))).~expressO(n). Return the arity of the given expression, i.e. the number of arguments that its type takes. > arity (val (0::Int)) 0 > arity (val False) 0 )> arity (value "id" (id :: Int -> Int)) 1 6> arity (value "const" (const :: Int -> Int -> Int)) 2 > arity (one -+- two) 0expressO(n). Returns the size of the given expression, i.e. the number of terminal values in it. zero = val (0 :: Int) one = val (1 :: Int) two = val (2 :: Int) xx -+- yy = value "+" ((+) :: Int->Int->Int) :$ xx :$ yy abs' xx = value "abs" (abs :: Int->Int) :$ xx  > size zero 1 > size (one -+- two) 3 > size (abs' one) 2expressO(n). Returns the maximum depth of a given expression given by the maximum number of nested function applications. Curried function application is counted  only once, i.e. the application of a two argument function increases the depth of both its arguments by one. (cf. )With zero = val (0 :: Int) one = val (1 :: Int) two = val (2 :: Int) xx -+- yy = value "+" ((+) :: Int->Int->Int) :$ xx :$ yy abs' xx = value "abs" (abs :: Int->Int) :$ xx > depth zero 1 > depth (one -+- two) 2 > depth (abs' one -+- two) 3Flipping arguments of applications in any of the subterms does not affect the result.expressO(n). Returns the maximum height of a given expression given by the maximum number of nested function applications. Curried function application is counted  each time, i.e. the application of a two argument function increases the depth of its first argument by two and of its second argument by one. (cf. )With: zero = val (0 :: Int) one = val (1 :: Int) two = val (2 :: Int) const' xx yy = value "const" (const :: Int->Int->Int) :$ xx :$ yy abs' xx = value "abs" (abs :: Int->Int) :$ xxThen: > height zero 1 > height (abs' one) 2 > height ((const' one) two) 3 $> height ((const' (abs' one)) two) 4 $> height ((const' one) (abs' two)) 3Flipping arguments of applications in subterms may change the result of the function.expressO(n). Does not evaluate values when comparing, but rather uses their representation as strings and their types..This instance works for ill-typed expressions.;Expressions come first when they have smaller complexity (l.) or when they come first lexicographically (m).expressO(n). Does not evaluate values when comparing, but rather uses their representation as strings and their types..This instance works for ill-typed expressions.expressShows Xs with their types. 9> show (value "not" not :$ val False) "not False :: Bool"*XYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~*XYZ[\]^efg_`ahtusrbcdpqlmn~vx|zwy}{okij(c) 2019-2021 Rudy Matela$3-Clause BSD (see the file LICENSE) Rudy Matela  Safe-InferredexpressO(n*m). Applies a function to all terminal values in an expression. (cf. ) Given that: > let zero = val (0 :: Int) > let one = val (1 :: Int) > let two = val (2 :: Int) > let three = val (3 :: Int) > let xx -+- yy = value "+" ((+) :: Int->Int->Int) :$ xx :$ yy > let intToZero e = if typ e == typ zero then zero else eThen: ,> one -+- (two -+- three) 1 + (2 + 3) :: Int > mapValues intToZero $ one -+- (two -+- three) 0 + (0 + 0) :: Integer$Given that the argument function is O(m), this function is O(n*m).expressO(n*m)8. Applies a function to all variables in an expression. Given that: > let primeify e = if isVar e | then case e of (Value n d) -> Value (n ++ "'") d | else e > let xx = var "x" (undefined :: Int) > let yy = var "y" (undefined :: Int) > let xx -+- yy = value "+" ((+) :: Int->Int->Int) :$ xx :$ yyThen: > xx -+- yy x + y :: Int > primeify xx x' :: Int -> mapVars primeify $ xx -+- yy x' + y' :: Int <> mapVars (primeify . primeify) $ xx -+- yy x'' + y'' :: Int$Given that the argument function is O(m), this function is O(n*m).expressO(n*m). Applies a function to all terminal constants in an expression. Given that: > let one = val (1 :: Int) > let two = val (2 :: Int) > let xx -+- yy = value "+" ((+) :: Int->Int->Int) :$ xx :$ yy > let intToZero e = if typ e == typ zero then zero else eThen: )> one -+- (two -+- xx) 1 + (2 + x) :: Int > mapConsts intToZero (one -+- (two -+- xx)) 0 + (0 + x) :: Integer$Given that the argument function is O(m), this function is O(n*m).expressO(n*m). Substitute subexpressions of an expression using the given function. Outer expressions have more precedence than inner expressions. (cf. )With: > let xx = var "x" (undefined :: Int) > let yy = var "y" (undefined :: Int) > let zz = var "z" (undefined :: Int) > let plus = value "+" ((+) :: Int->Int->Int) > let times = value "*" ((*) :: Int->Int->Int) > let xx -+- yy = plus :$ xx :$ yy > let xx -*- yy = times :$ xx :$ yy > let pluswap (o :$ xx :$ yy) | o == plus = Just $ o :$ yy :$ xx | pluswap _ = NothingThen: > mapSubexprs pluswap $ (xx -*- yy) -+- (yy -*- zz) y * z + x * y :: Int > mapSubexprs pluswap $ (xx -+- yy) -*- (yy -+- zz) (y + x) * (z + y) :: IntSubstitutions do not stack, in other words a replaced expression or its subexpressions are not further replaced: > mapSubexprs pluswap $ (xx -+- yy) -+- (yy -+- zz) (y + z) + (x + y) :: Int$Given that the argument function is O(m), this function is O(n*m).expressO(n*m). Substitute occurrences of values in an expression from the given list of substitutions. (cf. ) Given that: > let xx = var "x" (undefined :: Int) > let yy = var "y" (undefined :: Int) > let zz = var "z" (undefined :: Int) > let xx -+- yy = value "+" ((+) :: Int->Int->Int) :$ xx :$ yyThen: > ((xx -+- yy) -+- (yy -+- zz)) //- [(xx, yy), (zz, yy)] (y + y) + (y + y) :: Int > ((xx -+- yy) -+- (yy -+- zz)) //- [(yy, yy -+- zz)] (x + (y + z)) + ((y + z) + z) :: IntThis function does not work for substituting non-terminal subexpressions: 0> (xx -+- yy) //- [(xx -+- yy, zz)] x + y :: IntPlease use the slower + if you want the above replacement to work.Replacement happens only once: $> xx //- [(xx,yy), (yy,zz)] y :: Int(Given that the argument list has length m, this function is O(n*m).expressO(n*n*m). Substitute subexpressions in an expression from the given list of substitutions. (cf. ).Please consider using < if you are replacing just terminal values as it is faster. Given that: > let xx = var "x" (undefined :: Int) > let yy = var "y" (undefined :: Int) > let zz = var "z" (undefined :: Int) > let xx -+- yy = value "+" ((+) :: Int->Int->Int) :$ xx :$ yyThen: > ((xx -+- yy) -+- (yy -+- zz)) // [(xx -+- yy, yy), (yy -+- zz, yy)] y + y :: Int > ((xx -+- yy) -+- zz) // [(xx -+- yy, zz), (zz, xx -+- yy)] z + (x + y) :: IntReplacement happens only once with outer expressions having more precedence than inner expressions. <> (xx -+- yy) // [(yy,xx), (xx -+- yy,zz), (zz,xx)] z :: Int(Given that the argument list has length m, this function is O(n*n*m). Remember that since n= is the size of an expression, comparing two expressions is O(n)5 in the worst case, and we may need to compare with n" subexpressions in the worst case.expressRename variables in an X. 2> renameVarsBy (++ "'") (xx -+- yy) x' + y' :: Int > renameVarsBy (++ "'") (yy -+- (zz -+- xx)) (y' + (z' + x')) :: Int /> renameVarsBy (++ "1") (abs' xx) abs x1 :: Int ?> renameVarsBy (++ "2") $ abs' (xx -+- yy) abs (x2 + y2) :: IntNOTE: this will affect holes! (c) 2019-2021 Rudy Matela$3-Clause BSD (see the file LICENSE) Rudy Matela  Safe-InferredA expressO(1) . Creates a ^&iable with the same type as the given X. 9> let one = val (1::Int) > "x" `varAsTypeOf` one x :: Int '> "p" `varAsTypeOf` val False p :: BoolexpressO(1). Creates an X7 representing a typed hole with the type of the given X. (cf. ) >> val (1::Int) 1 :: Int > holeAsTypeOf $ val (1::Int) _ :: IntexpressO(1). Creates an X6 representing a typed hole of the given argument type. "> hole (undefined :: Int) _ :: Int 4> hole (undefined :: Maybe String) _ :: Maybe [Char]A hole is represented as a variable with no name or a value named "_": &hole x = var "" x hole x = value "_" xexpressO(1). Checks if an X represents a typed hole. (cf. ) '> isHole $ hole (undefined :: Int) True ,> isHole $ value "not" not :$ val True False > isHole $ val 'a' FalseexpressO(n). Lists all holes in an expression, in order and with repetitions. (cf. ) .> holes $ hole (undefined :: Bool) [_ :: Bool] > holes $ value "&&" (&&) :$ hole (undefined :: Bool) :$ hole (undefined :: Bool) [_ :: Bool,_ :: Bool] > holes $ hole (undefined :: Bool->Bool) :$ hole (undefined::Bool) [_ :: Bool -> Bool,_ :: Bool]expressO(n^2)?. Lists all holes in an expression without repetitions. (cf. ) 1> nubHoles $ hole (undefined :: Bool) [_ :: Bool] > nubHoles $ value "&&" (&&) :$ hole (undefined :: Bool) :$ hole (undefined :: Bool) [_ :: Bool] > nubHoles $ hole (undefined :: Bool->Bool) :$ hole (undefined::Bool) [_ :: Bool,_ :: Bool -> Bool]Runtime averages to  O(n log n), on evenly distributed expressions such as (f x + g y) + (h z + f w) ; and to O(n^2) on deep expressions such as f (g (h (f (g (h x))))).expressO(n)0. Returns whether an expression contains a hole )> hasHole $ hole (undefined :: Bool) True -> hasHole $ value "not" not :$ val True False <> hasHole $ value "not" not :$ hole (undefined :: Bool) TrueexpressO(n). Returns whether an expression is complete. A complete expression is one without holes. -> isComplete $ hole (undefined :: Bool) False /> isComplete $ value "not" not :$ val True True > isComplete $ value "not" not :$ hole (undefined :: Bool) False is the negation of . isComplete = not . hasHole is to  what q is to p.expressGenerate an infinite list of variables based on a template and a given type. (cf. ) > putL 10 $ listVars "x" (undefined :: Int) [ x :: Int , y :: Int , z :: Int , x' :: Int , y' :: Int , z' :: Int , x'' :: Int , ... ] > putL 10 $ listVars "p" (undefined :: Bool) [ p :: Bool , q :: Bool , r :: Bool , p' :: Bool , q' :: Bool , r' :: Bool , p'' :: Bool , ... ]expressGenerate an infinite list of variables based on a template and the type of a given X. (cf. ) > let one = val (1::Int) > putL 10 $ "x" `listVarsAsTypeOf` one [ x :: Int , y :: Int , z :: Int , x' :: Int , ... ] > let false = val False > putL 10 $ "p" `listVarsAsTypeOf` false [ p :: Bool , q :: Bool , r :: Bool , p' :: Bool , ... ]express0Fill holes in an expression with the given list. > let i_ = hole (undefined :: Int) > let e1 -+- e2 = value "+" ((+) :: Int -> Int -> Int) :$ e1 :$ e2 > let xx = var "x" (undefined :: Int) > let yy = var "y" (undefined :: Int) (> fill (i_ -+- i_) [xx, yy] x + y :: Int (> fill (i_ -+- i_) [xx, xx] x + x :: Int > let one = val (1::Int) 8> fill (i_ -+- i_) [one, one -+- one] 1 + (1 + 1) :: Int-This function silently remaining expressions: > fill i_ [xx, yy] x :: Int-This function silently keeps remaining holes: 5> fill (i_ -+- i_ -+- i_) [xx, yy] (x + y) + _ :: IntThis function silently skips remaining holes if one is not of the right type: >> fill (i_ -+- i_ -+- i_) [xx, val 'c', yy] (x + _) + _ :: Int   (c) 2019-2021 Rudy Matela$3-Clause BSD (see the file LICENSE) Rudy Matela  Safe-Inferred3expressO(n). Folds a list of X with function application (Z ). This reverses the effect of o. foldApp [e0] = e0 foldApp [e0,e1] = e0 :$ e1 foldApp [e0,e1,e2] = e0 :$ e1 :$ e2 foldApp [e0,e1,e2,e3] = e0 :$ e1 :$ e2 :$ e3 Remember Z is left-associative, so: foldApp [e0] = e0 foldApp [e0,e1] = (e0 :$ e1) foldApp [e0,e1,e2] = ((e0 :$ e1) :$ e2) foldApp [e0,e1,e2,e3] = (((e0 :$ e1) :$ e2) :$ e3)This function may! produce an ill-typed expression.expressO(1). Folds a pair of X values into a single X. (cf. )This always# generates an ill-typed expression. > foldPair (val False, val (1::Int)) (False,1) :: ill-typed # ExprPair $ Bool # > foldPair (val (0::Int), val True) (0,True) :: ill-typed # ExprPair $ Int #9This is useful when applying transformations on pairs of X s, such as ,  or . > let ii = var "i" (undefined::Int) > let kk = var "k" (undefined::Int) > unfoldPair $ canonicalize $ foldPair (ii,kk) (x :: Int,y :: Int)expressO(1). Unfolds an X3 representing a pair. This reverses the effect of . > value "," ((,) :: Bool->Bool->(Bool,Bool)) :$ val True :$ val False (True,False) :: (Bool,Bool) > unfoldPair $ value "," ((,) :: Bool->Bool->(Bool,Bool)) :$ val True :$ val False (True :: Bool,False :: Bool)expressO(n). Folds a list of Xs into a single X. (cf. )This always# generates an ill-typed expression. fold [val False, val True, val (1::Int)] [False,True,1] :: ill-typed # ExprList $ Bool #9This is useful when applying transformations on lists of X s, such as ,  or . > let ii = var "i" (undefined::Int) > let kk = var "k" (undefined::Int) > let qq = var "q" (undefined::Bool) > let notE = value "not" not > unfold . canonicalize . fold $ [ii,kk,notE :$ qq, notE :$ val False] [x :: Int,y :: Int,not p :: Bool,not False :: Bool]expressO(n). Unfolds an X$ representing a list into a list of X s. This reverses the effect of . > expr [1,2,3::Int] [1,2,3] :: [Int] > unfold $ expr [1,2,3::Int] [1 :: Int,2 :: Int,3 :: Int]oo (c) 2019-2021 Rudy Matela$3-Clause BSD (see the file LICENSE) Rudy Matela  Safe-Inferredexpress typeclass instances provide an  function that allows values to be deeply encoded as applications of Xs. expr False = val False expr (Just True) = value "Just" (Just :: Bool -> Maybe Bool) :$ val True The function % can be contrasted with the function \:\! always encodes values as atomic Y Xs -- shallow encoding.. ideally encodes expressions as applications (Z ) between Y Xs -- deep encoding.>Depending on the situation, one or the other may be desirable.>Instances can be automatically derived using the TH function  .8The following example shows a datatype and its instance: (data Stack a = Stack a (Stack a) | Empty instance Express a => Express (Stack a) where expr s@(Stack x y) = value "Stack" (Stack ->>: s) :$ expr x :$ expr y expr s@Empty = value "Empty" (Empty -: s) To declare < it may be useful to use auxiliary type binding operators: , , , , , , ...+For types with atomic values, just declare  expr = val expressType restricted version of const that forces its first argument to have the same type as the second. + value -: (undefined :: Ty) = value :: TyexpressType restricted version of const that forces the result of its first argument to have the same type as the second. ) f ->: (undefined :: Ty) = f :: a -> TyexpressType restricted version of const that forces the result of the result of its first argument to have the same type as the second. .f ->>: (undefined :: Ty) = f :: a -> b -> TyexpressType restricted version of const that forces the result of the result of the result of its first argument to have the same type as the second.express0Forces the result type of a 4-argument function.express0Forces the result type of a 5-argument function.express0Forces the result type of a 6-argument function.express0Forces the result type of a 7-argument function.express0Forces the result type of a 8-argument function.express0Forces the result type of a 9-argument function.express1Forces the result type of a 10-argument function.express1Forces the result type of a 11-argument function.express1Forces the result type of a 12-argument function. 1111111111111 (c) 2019-2021 Rudy Matela$3-Clause BSD (see the file LICENSE) Rudy Matela Noneexpress Derives an  instance for the given type .This function needs the TemplateHaskell extension.If , , , 7, ... are not in scope, this will derive them as well.expressSame as 4 but does not warn when instance already exists ( is preferable).express Derives a  instance for a given type 3 cascading derivation of type arguments as well.(c) 2019-2021 Rudy Matela$3-Clause BSD (see the file LICENSE) Rudy Matela  Safe-InferredlXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ (c) 2019-2021 Rudy Matela$3-Clause BSD (see the file LICENSE) Rudy Matela  Safe-Inferred2express!Given two expressions, returns a   list of matches of subexpressions of the first expressions to variables in the second expression. Returns   when there is no match. > let zero = val (0::Int) > let one = val (1::Int) > let xx = var "x" (undefined :: Int) > let yy = var "y" (undefined :: Int) > let e1 -+- e2 = value "+" ((+)::Int->Int->Int) :$ e1 :$ e2 > (zero -+- one) `match` (xx -+- yy) Just [(y :: Int,1 :: Int),(x :: Int,0 :: Int)] > (zero -+- (one -+- two)) `match` (xx -+- yy) Just [(y :: Int,1 + 2 :: Int),(x :: Int,0 :: Int)] ?> (zero -+- (one -+- two)) `match` (xx -+- (yy -+- yy)) Nothing In short:  (zero -+- one) `match` (xx -+- yy) = Just [(xx,zero), (yy,one)] (zero -+- (one -+- two)) `match` (xx -+- yy) = Just [(xx,zero), (yy,one-+-two)] (zero -+- (one -+- two)) `match` (xx -+- (yy -+- yy)) = NothingexpressLike " but allowing predefined bindings. matchWith [(xx,zero)] (zero -+- one) (xx -+- yy) = Just [(xx,zero), (yy,one)] matchWith [(xx,one)] (zero -+- one) (xx -+- yy) = Nothingexpress Given two Xs, checks if the first expression is an instance of the second in terms of variables. (cf. , ) > let zero = val (0::Int) > let one = val (1::Int) > let xx = var "x" (undefined :: Int) > let yy = var "y" (undefined :: Int) > let e1 -+- e2 = value "+" ((+)::Int->Int->Int) :$ e1 :$ e2  one `isInstanceOf` one = True xx `isInstanceOf` xx = True yy `isInstanceOf` xx = True zero `isInstanceOf` xx = True xx `isInstanceOf` zero = False one `isInstanceOf` zero = False (xx -+- (yy -+- xx)) `isInstanceOf` (xx -+- yy) = True (yy -+- (yy -+- xx)) `isInstanceOf` (xx -+- yy) = True (zero -+- (yy -+- xx)) `isInstanceOf` (zero -+- yy) = True (one -+- (yy -+- xx)) `isInstanceOf` (zero -+- yy) = Falseexpress Given two Xs, checks if the first expression encompasses the second expression in terms of variables.0This is equivalent to flipping the arguments of . zero `encompasses` xx = False xx `encompasses` zero = Trueexpress:Checks if any of the subexpressions of the first argument X( is an instance of the second argument X.expressO(n^2). Checks if an X is a subexpression of another. 5> (xx -+- yy) `isSubexprOf` (zz -+- (xx -+- yy)) True 2> (xx -+- yy) `isSubexprOf` abs' (yy -+- xx) False > xx `isSubexprOf` yy False(c) 2019-2021 Rudy Matela$3-Clause BSD (see the file LICENSE) Rudy Matela  Safe-InferredzexpressO(1). Reifies an   instance into a list of Xs. The list will contain   and   for the given type. (cf. , ) > reifyEq (undefined :: Int) [ (==) :: Int -> Int -> Bool , (/=) :: Int -> Int -> Bool ] > reifyEq (undefined :: Bool) [ (==) :: Bool -> Bool -> Bool , (/=) :: Bool -> Bool -> Bool ] > reifyEq (undefined :: String) [ (==) :: [Char] -> [Char] -> Bool , (/=) :: [Char] -> [Char] -> Bool ]expressO(1). Reifies an   instance into a list of Xs. The list will contain  ,   and   for the given type. (cf. , , , ) > reifyOrd (undefined :: Int) [ (<=) :: Int -> Int -> Bool , (<) :: Int -> Int -> Bool ] > reifyOrd (undefined :: Bool) [ (<=) :: Bool -> Bool -> Bool , (<) :: Bool -> Bool -> Bool ] > reifyOrd (undefined :: [Bool]) [ (<=) :: [Bool] -> [Bool] -> Bool , (<) :: [Bool] -> [Bool] -> Bool ]expressO(1). Reifies   and   instances into a list of X.expressO(1). Reifies a  instance into a list of Xs. The list will contain  for the given type. (cf. , , ) 6> reifyName (undefined :: Int) [name :: Int -> [Char]] 8> reifyName (undefined :: Bool) [name :: Bool -> [Char]]expressO(1). Builds a reified   instance from the given   function. (cf. ) > mkEq ((==) :: Int -> Int -> Bool) [ (==) :: Int -> Int -> Bool , (/=) :: Int -> Int -> Bool ]expressO(1). Builds a reified   instance from the given   function. (cf. , )expressO(1). Builds a reified   instance from the given   function. (cf. , )expressO(1). Builds a reified  instance from the given  function. (cf. , )expressO(1). Builds a reified  instance from the given  and type. (cf. , )expressO(n). Returns whether an  < instance exists in the given instances list for the given  . > isEqT (reifyEqOrd (undefined :: Int)) (typeOf (undefined :: Int)) True > isEqT (reifyEqOrd (undefined :: Int)) (typeOf (undefined :: [[[Int]]])) False)Given that the instances list has length n, this function is O(n).expressO(n). Returns whether an  < instance exists in the given instances list for the given  . > isOrdT (reifyEqOrd (undefined :: Int)) (typeOf (undefined :: Int)) True > isOrdT (reifyEqOrd (undefined :: Int)) (typeOf (undefined :: [[[Int]]])) False)Given that the instances list has length n, this function is O(n).expressO(n). Returns whether both   and  1 instance exist in the given list for the given  .)Given that the instances list has length n, this function is O(n).expressO(n+m). Returns whether an  < instance exists in the given instances list for the given X. :> isEq (reifyEqOrd (undefined :: Int)) (val (0::Int)) True > isEq (reifyEqOrd (undefined :: Int)) (val ([[[0::Int]]])) False)Given that the instances list has length m and that the given X has size n, this function is O(n+m).expressO(n+m). Returns whether an  < instance exists in the given instances list for the given X. ;> isOrd (reifyEqOrd (undefined :: Int)) (val (0::Int)) True > isOrd (reifyEqOrd (undefined :: Int)) (val ([[[0::Int]]])) False)Given that the instances list has length m and that the given X has size n, this function is O(n+m).expressO(n+m). Returns whether both   and  1 instance exist in the given list for the given X.)Given that the instances list has length m and that the given X has size n, this function is O(n+m). 1(c) 2019-2021 Rudy Matela$3-Clause BSD (see the file LICENSE) Rudy Matela  Safe-InferredV expressLike  but allows customization of the list of variable names. (cf. , ) > canonicalizeWith (const ["i","j","k","l",...]) (xx -+- yy) i + j :: Int The argument X of the argument function allows to provide a different list of names for different types: > let namesFor e > | typ e == typeOf (undefined::Char) = variableNamesFromTemplate "c1" > | typ e == typeOf (undefined::Int) = variableNamesFromTemplate "i" > | otherwise = variableNamesFromTemplate "x" > canonicalizeWith namesFor ((xx -+- ord' dd) -+- (ord' cc -+- yy)) (i + ord c1) + (ord c2 + j) :: IntexpressLike  but allows customization of the list of variable names. (cf. , )expressLike 3 but allows specifying the list of variable names.expressCanonicalizes an X so that variable names appear in order. Variable names are taken from the . '> canonicalize (xx -+- yy) x + y :: Int '> canonicalize (yy -+- xx) x + y :: Int '> canonicalize (xx -+- xx) x + x :: Int '> canonicalize (yy -+- yy) x + x :: IntConstants are untouched: > canonicalize (jj -+- (zero -+- abs' ii)) x + (y + abs y) :: Int'This also works for variable functions: > canonicalize (gg yy -+- ff xx -+- gg xx) (f x + g y) + f y :: Intexpress Return a canonicalization of an X3 that makes variable names appear in order using  as provided by  . By using  it can  Xs. > canonicalization (gg yy -+- ff xx -+- gg xx) [ (x :: Int, y :: Int) , (f :: Int -> Int, g :: Int -> Int) , (y :: Int, x :: Int) , (g :: Int -> Int, f :: Int -> Int) ] > canonicalization (yy -+- xx -+- yy) [ (x :: Int, y :: Int) , (y :: Int, x :: Int) ]expressReturns whether an X is canonical: if applying  is an identity using  as provided by .express'Returns all canonical variations of an X by filling holes with variables. Where possible, variations are listed from most general to least general. %> canonicalVariations $ i_ [x :: Int] > canonicalVariations $ i_ -+- i_ [ x + y :: Int , x + x :: Int ] > canonicalVariations $ i_ -+- i_ -+- i_ [ (x + y) + z :: Int , (x + y) + x :: Int , (x + y) + y :: Int , (x + x) + y :: Int , (x + x) + x :: Int ] 9> canonicalVariations $ i_ -+- ord' c_ [x + ord c :: Int] > canonicalVariations $ i_ -+- i_ -+- ord' c_ [ (x + y) + ord c :: Int , (x + x) + ord c :: Int ] > canonicalVariations $ i_ -+- i_ -+- length' (c_ -:- unit c_) [ (x + y) + length (c:d:"") :: Int , (x + y) + length (c:c:"") :: Int , (x + x) + length (c:d:"") :: Int , (x + x) + length (c:c:"") :: Int ]In an expression without holes this functions just returns a singleton list with the expression itself: 1> canonicalVariations $ val (0 :: Int) [0 :: Int] 1> canonicalVariations $ ord' bee [ord 'b' :: Int]When applying this to expressions already containing variables clashes are avoided and these variables are not touched: > canonicalVariations $ i_ -+- ii -+- jj -+- i_ [ x + i + j + y :: Int , x + i + j + y :: Int ] 0> canonicalVariations $ ii -+- jj [i + j :: Int] > canonicalVariations $ xx -+- i_ -+- i_ -+- length' (c_ -:- unit c_) -+- yy [ (((x + z) + x') + length (c:d:"")) + y :: Int , (((x + z) + x') + length (c:c:"")) + y :: Int , (((x + z) + z) + length (c:d:"")) + y :: Int , (((x + z) + z) + length (c:c:"")) + y :: Int ]express3Returns the most general canonical variation of an X" by filling holes with variables. -> mostGeneralCanonicalVariation $ i_ x :: Int 8> mostGeneralCanonicalVariation $ i_ -+- i_ x + y :: Int > mostGeneralCanonicalVariation $ i_ -+- i_ -+- i_ (x + y) + z :: Int > mostGeneralCanonicalVariation $ i_ -+- ord' c_ x + ord c :: Int > mostGeneralCanonicalVariation $ i_ -+- i_ -+- ord' c_ (x + y) + ord c :: Int > mostGeneralCanonicalVariation $ i_ -+- i_ -+- length' (c_ -:- unit c_) (x + y) + length (c:d:"") :: IntIn an expression without holes this functions just returns the given expression itself: 9> mostGeneralCanonicalVariation $ val (0 :: Int) 0 :: Int 9> mostGeneralCanonicalVariation $ ord' bee ord 'b' :: Int(This function is the same as taking the  of  but a bit faster.express4Returns the most specific canonical variation of an X" by filling holes with variables. .> mostSpecificCanonicalVariation $ i_ x :: Int 9> mostSpecificCanonicalVariation $ i_ -+- i_ x + x :: Int > mostSpecificCanonicalVariation $ i_ -+- i_ -+- i_ (x + x) + x :: Int > mostSpecificCanonicalVariation $ i_ -+- ord' c_ x + ord c :: Int > mostSpecificCanonicalVariation $ i_ -+- i_ -+- ord' c_ (x + x) + ord c :: Int > mostSpecificCanonicalVariation $ i_ -+- i_ -+- length' (c_ -:- unit c_) (x + x) + length (c:c:"") :: IntIn an expression without holes this functions just returns the given expression itself: :> mostSpecificCanonicalVariation $ val (0 :: Int) 0 :: Int :> mostSpecificCanonicalVariation $ ord' bee ord 'b' :: Int(This function is the same as taking the  of  but a bit faster.expressA faster version of  that disregards name clashes across different types. Results are confusing to the user but fine for Express which differentiates between variables with the same name but different types.Without applying , the following X% may seem to have only one variable: => fastCanonicalVariations $ i_ -+- ord' c_ [x + ord x :: Int](Where in fact it has two, as the second  x ! has a different type. Applying  disambiguates: > map canonicalize . fastCanonicalVariations $ i_ -+- ord' c_ [x + ord c :: Int]'This function is useful when resulting Xs are not intended to be presented to the user but instead to be used by another function. It is simply faster to skip the step where clashes are resolved.expressA faster version of  that disregards name clashes across different types. Consider using  instead.The same caveats of  do apply here.expressA faster version of  that disregards name clashes across different types. Consider using  instead.The same caveats of  do apply here.  (c) 2019-2021 Rudy Matela$3-Clause BSD (see the file LICENSE) Rudy Matela NoneDEFXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~XYZ[\]^efg_`ahtusrbcdpqlmn~kjivx|zwy}{oDFE(c) 2019-2021 Rudy Matela$3-Clause BSD (see the file LICENSE) Rudy Matela NoneexpressX representing a hole of   type. > b_ _ :: BoolexpressX representing a variable p ::  . > pp p :: BoolexpressX representing a variable q ::  . > qq q :: BoolexpressX representing a variable r ::  . > rr r :: BoolexpressX representing a variable p' ::  . > pp' p' :: Boolexpress  encoded as an X. > false False :: Boolexpress  encoded as an X. > true True :: Boolexpress The function   encoded as an X. > notE not :: Bool -> Boolexpress The function  encoded as an X. #> andE (&&) :: Bool -> Bool -> Boolexpress The function  encoded as an X. "> orE (||) :: Bool -> Bool -> Boolexpress The function   lifted over the X type. > not' false not False :: Bool > evalBool $ not' false True > not' pp not p :: Boolexpress The function   lifted over the X type. > pp -&&- qq p && q :: Bool '> false -&&- true False && True :: Bool "> evalBool $ false -&&- true Falseexpress The function   lifted over the X type. > pp -||- qq p || q :: Bool '> false -||- true False || True :: Bool !> evalBool $ false -||- true TrueexpressA typed hole of   type.  > i_ _ :: Intexpress A variable x of   type.  > xx x :: Intexpress A variable y of   type.  > yy y :: Intexpress A variable z of   type.  > zz z :: Intexpress A variable x' of   type. > xx' x' :: Intexpress A variable i of   type.  > ii i :: Intexpress A variable j of   type.  > jj j :: Intexpress A variable k of   type.  > kk k :: Intexpress A variable i' of   type. > ii' i' :: Intexpress A variable l of   type.  > ll l :: Intexpress A variable m of   type.  > mm m :: Intexpress A variable n of   type.  > nn n :: Intexpress The value 0 bound to the   type encoded as an X. > zero 0 :: Intexpress The value 1 bound to the   type encoded as an X. > one 1 :: Intexpress The value 2 bound to the   type encoded as an X. > two 2 :: Intexpress The value 3 bound to the   type encoded as an X. > three 3 :: Intexpress The value -1 bound to the   type encoded as an X. > minusOne -1 :: Intexpress The value -2 bound to the   type encoded as an X. > minusOne -2 :: IntexpressA variable function f& of 'Int -> Int' type lifted over the X type. > ff xx f x :: Int > ff one f 1 :: Intexpress A variable f$ of 'Int -> Int' type encoded as an X. > ffE f :: Int -> IntexpressA variable function g& of 'Int -> Int' type lifted over the X type. > gg yy g y :: Int > gg minusTwo gg (-2) :: IntexpressA variable binary operator ? lifted over the X type. Works for  ,  , , [Int] and . > xx -?- yy x ? y :: Int > pp -?- qq p ? q :: Bool > xx -?- qq *** Exception: (-?-): cannot apply `(?) :: * -> * -> *` to `x :: Int' and `q :: Bool'. Unhandled types?express A variable g$ of 'Int -> Int' type encoded as an X. > ggE g :: Int -> Intexpress The operator   for the   type for use on Xs. (See also .) > two -+- three 2 + 3 :: Int 9> minusOne -+- minusTwo -+- zero ((-1) + (-2)) + 0 :: Int '> xx -+- (yy -+- zz) x + (y + z) :: Intexpress The operator   for the   type. (See also .) > plus (+) :: Int -> Int -> Int !> plus :$ one (1 +) :: Int -> Int > plus :$ xx :$ yy x + y :: Intexpress The operator   for the   type lifted over the X type. (See also .) > three -*- three 9 :: Int *> one -*- two -*- three (1 * 2) * 3 :: Int > two -*- xx 2 * x :: Intexpress The operator   for the   type. (See also .)  > times (*) :: Int -> Int -> Int "> times :$ two (2 *) :: Int -> Int  > times :$ xx :$ yy x * y :: IntexpressConstructs an application of   as an X. Only works for  ,  , , , [Int], [Bool]. > id' yy id yy :: Int > id' one id 1 :: Int > evl (id' one) :: Int 1 > id' pp id p :: Bool > id' false id' False :: Bool %> evl (id' true) :: Bool True :: Boolexpress The function   for the   type encoded as an X . (See also .) > idE :$ xx id x :: Int > idE :$ zero id 0 :: Int ,> evaluate $ idE :$ zero :: Maybe Int Just 0express The function   encoded as an X. (cf. )express The function   encoded as an X. (cf. )express The function   encoded as an X. (cf. )express The function   encoded as an X. (cf. )express The function   encoded as an X. (cf. )express The function   encoded as an X. (cf. )express  over the   type lifted over the X type. > negate' xx negate x :: Int > evl (negate' one) :: Int -1express  over the   type encoded as an X > negateE negate :: Int -> Intexpress  over the   type lifted over the X type. > abs' xx' abs x' :: Int > evl (abs' minusTwo) :: Int 2express  over the   type encoded as an X. > absE abs :: Int -> Intexpress A hole of  type encoded as an X. > c_ _ :: CharexpressThe character 'b' encoded as an X > bee 'b' :: Char > evl bee :: Char 'b'expressThe character 'c' encoded as an X > cee 'c' :: Char > evl cee :: Char 'c'expressThe character 'd' encoded as an X > dee 'd' :: Char > evl dee :: Char 'd'expressA typed hole of [Int] type encoded as an X. > is_ _ :: [Int]expressA variable named xs of type [Int] encoded as an X. > xxs xs :: [Int]expressA variable named ys of type [Int] encoded as an X. > yys ys :: [Int]expressAn empty list of type [Int] encoded as an X. > nil [] :: [Int]express An empty  encoded as an X. > emptyString "" :: Stringexpress"The empty list '[]' encoded as an X.express"The empty list '[]' encoded as an X.express"The empty list '[]' encoded as an X.expressThe list constructor with   as element type encoded as an X. #> cons (:) :: Int -> [Int] -> [Int] !> cons :$ one :$ nil [1] :: [Int]Consider using  and  when building lists of X.expressThe list constructor  :  encoded as an X.expressThe list constructor  :  encoded as an X.expressThe list constructor  :  encoded as an X.express constructs a list with a single element. This works for elements of type  ,  and  . > unit one [1] > unit false [False]express%The list constructor lifted over the X& type. Works for the element types  ,  and  . ,> zero -:- one -:- unit two [0,1,2] :: [Int] /> zero -:- one -:- two -:- nil [0,1,2] :: [Int] !> bee -:- unit cee "bc" :: [Char]express#List concatenation lifted over the X& type. Works for the element types  ,  and  . > (zero -:- one -:- nil) -:- (two -:- three -:- nil) [0,1] -++- [2,3] :: [Int] 9> (bee -:- unit cee) -:- unit dee "bc" -++- "c" :: [Char]expressList  lifted over the X& type. Works for the element types  ,  and  . "> head' $ unit one head [1] :: Int #> head' $ unit bee head "b" :: Char -> head' $ zero -:- unit two head [0,2] :: Int !> evl $ head' $ unit one :: Int 1expressList  lifted over the X& type. Works for the element types  ,  and  . $> tail' $ unit one tail [1] :: [Int] %> tail' $ unit bee tail "b" :: [Char] /> tail' $ zero -:- unit two tail [0,2] :: [Int] .> evl $ tail' $ zero -:- unit two :: [Int] [2]expressList  lifted over the X& type. Works for the element types  ,  and  . #> null' $ unit one null [1] :: Bool > null' $ nil null [] :: Bool > evl $ null' nil :: Bool TrueexpressList  lifted over the X& type. Works for the element types  ,  and  . &> length' $ unit one length [1] :: Int &> length' $ unit bee length "b" :: Int 1> length' $ zero -:- unit two length [0,2] :: Int #> evl $ length' $ unit one :: Int 1expressA virtual function if :: Bool -> a -> a -> a lifted over the X/ type. This is displayed as an if-then-else. ,> if' pp zero xx (if p then 0 else x) :: Int 5> zz -*- if' pp xx yy z * (if p then x else y) :: Int > if' pp false true -||- if' qq true false (if p then False else True) || (if q then True else False) :: Bool 0> evl $ if' true (val 't') (val 'f') :: Char 't'expressA typed hole of [Bool] type encoded as an X. > bs_ _ :: [Bool]expressX representing a variable p' :: `[Bool]`. > pps ps :: [Bool]expressA typed hole of '[Bool]' type > qqs qs :: [Bool]express lifted over the X type. > and' pps and ps :: Bool .> evl (and' $ expr [False,True]) :: Bool Falseexpress lifted over the X type. > or' pps or ps :: Bool ,> evl (or' $ expr [False,True]) :: Bool Trueexpress of   elements lifted over the X type. > sum' xxs sum xs :: Int )> evl (sum' $ expr [1,2,3::Int]) :: Int 6express of   elements lifted over the X type.  > product' xxs product xs :: Int -> evl (product' $ expr [1,2,3::Int]) :: Int 6DEFXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 032675564444  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~                                                            N   )                                                                                                                                                                                             %express-0.1.10-5qKvUIySI7ZLOZKdoBSF9SData.Express.Utils.ListData.Express.Utils.StringData.Express.NameData.Express.Utils.THData.Express.Name.DeriveData.Express.Utils.TypeableData.Express.CoreData.Express.MapData.Express.HoleData.Express.FoldData.Express.ExpressData.Express.Express.DeriveData.Express.MatchData.Express.InstancesData.Express.CanonData.Express.Fixtures canonicalize mapValuescanonicalVariations deriveExpressData.Express.Basic Data.ExpressnubSort nubSortBy isSubsetOfisPermutationOfisNublookupId+++unquoteatomicouternmostPrecisNegativeLiteralisInfixprecisPrefixisInfixedPrefixtoPrefix primeCyclevariableNamesFromTemplateNamenamenames$fName(,,,,,,,,,,,)$fName(,,,,,,,,,,)$fName(,,,,,,,,,)$fName(,,,,,,,,)$fName(,,,,,,,)$fName(,,,,,,) $fName(,,,,,) $fName(,,,,) $fNameWord$fName[] $fName(,,,) $fName(,,) $fName(,) $fNameEither $fNameMaybe$fName-> $fNameDouble $fNameFloat $fNameRatio$fNameOrdering $fNameChar $fNameInteger $fNameInt $fNameBool$fName()deriveWhenNeededderiveWhenNeededOrWarn showJustNamereallyDeriveCascading typeConArgstypeConArgsThattypeConCascadingArgsThat normalizeTypenormalizeTypeUnits isInstanceOfisntInstanceOf typeAritytypeConstructors isTypeSynonymtypeSynonymType|=>||++| mergeIFnsmergeIwhereItypeConstructorsArgNames lookupValN deriveNamederiveNameIfNeededderiveNameCascading compareTytyArity finalResultTyunFunTy argumentTyresultTy elementTyboolTyintTy orderingTyfunTyConisFunTymkComparisonTy mkCompareTytypesIn typesInList->::ExprValue:$valueval$$vartypetypmtyp isIllTyped isWellTypedisFunevaluateevalevl toDynamic showOpExpr showPrecExprshowExprcompareComplexitycompareLexicographicallycompareQuickly unfoldApphasVarisGroundisConstisVarisValueisAppsubexprs nubSubexprsvalues nubValuesconsts nubConstsvarsnubVarsaritysizedepthheight $fOrdExpr$fEqExpr $fShowExprmapVars mapConsts mapSubexprs//-// renameVarsBy varAsTypeOf holeAsTypeOfholeisHoleholesnubHoleshasHole isCompletelistVarslistVarsAsTypeOffillfoldAppfoldPair unfoldPairfoldTrio unfoldTriofoldunfoldExpressexpr-:->:->>:->>>:->>>>:->>>>>:->>>>>>: ->>>>>>>: ->>>>>>>>: ->>>>>>>>>: ->>>>>>>>>>: ->>>>>>>>>>>:->>>>>>>>>>>>:$fExpress(,,,,,,,,,,,)$fExpress(,,,,,,,,,,)$fExpress(,,,,,,,,,)$fExpress(,,,,,,,,)$fExpress(,,,,,,,)$fExpress(,,,,,,)$fExpress(,,,,,)$fExpress(,,,,)$fExpressRatio $fExpress[]$fExpress(,,,) $fExpress(,,) $fExpress(,)$fExpressEither$fExpressMaybe$fExpressOrdering $fExpressChar$fExpressInteger $fExpressInt $fExpressBool $fExpress()deriveExpressIfNeededderiveExpressCascadingmatch matchWith encompasses hasInstanceOf isSubexprOfreifyEqreifyOrd reifyEqOrd reifyNamemkEqmkOrdmkOrdLessEqualmkName mkNameWithlookupComparisonisEqTisOrdTisEqOrdTisEqisOrdisEqOrd mkComparison mkEquationmkComparisonLTmkComparisonLE lookupName lookupNames listVarsWith validApps findValidApppreludeNameInstancescanonicalizeWithcanonicalizationWithisCanonicalWithcanonicalization isCanonicalmostGeneralCanonicalVariationmostSpecificCanonicalVariationfastCanonicalVariationsfastMostGeneralVariationfastMostSpecificVariationb_ppqqrrpp'falsetruenotEandEorE-==>-impliesnot'-&&--||-i_xxyyzzxx'iijjkkii'llmmnnzeroonetwothreeminusOneminusTwoffffEgg-?-ggE-+-plus-*-timesid'idEidIntidBoolidCharidIntsidBoolsidStringconst'negate'negateEabs'absEodd'even'c_ccddccsaebeeceedeespace lineBreakord'ordEis_xxsyysnil emptyStringnilIntnilBoolnilCharconsconsIntconsBoolconsCharunit-:- appendInt-++-head'tail'null'length'sort'insert'elem'-$--==--/=--<=--<-if'compare'nothing nothingInt nothingBooljustIntjustBooljust-|-paircommatriple quadruple quintuplesixtuplebs_ppsqqsand'or'sum'product'baseGHC.ListlookupGHC.Base++filterzipmap Data.Foldableelemminimummaximumfoldr1productsumfoldl1foldl'nullfoldlfoldrlength Data.ListisSubsequenceOfData.Traversable mapAccumR mapAccumLfindnotElem minimumBy maximumByallanyorand concatMapconcat Data.OldListunwordswordsunlineslinesunfoldrsortOnsortBysort permutations subsequencestailsinitsgroupBygroupdeleteFirstsByunzip7unzip6unzip5unzip4zipWith7zipWith6zipWith5zipWith4zip7zip6zip5zip4genericReplicate genericIndexgenericSplitAt genericDrop genericTake genericLengthinsertByinsert partition transpose intercalate intersperse intersectBy intersectunionByunion\\deleteBydeletenubBynub isInfixOf isSuffixOf isPrefixOf findIndices findIndex elemIndices elemIndex stripPrefix dropWhileEndunzip3unzipzipWith3zipWithzip3!!reversebreakspansplitAtdroptake dropWhile takeWhilecycle replicaterepeatiterate'iteratescanr1scanrscanl'scanl1scanlfoldl1'initlasttailunconshead Data.StringIsString fromStringghc-prim GHC.TypesChar Data.Char isSeparatorisNumberisMarkisLetter digitToIntGHC.Read readLitChar lexLitChar GHC.UnicodetoTitletoUppertoLowerisLowerisUpperisPrint isControl isAlphaNumisAlphaisSymbol isPunctuation isHexDigit isOctDigitisDigitisSpace isAsciiUpper isAsciiLowerisLatin1isAsciigeneralCategoryGeneralCategory NotAssigned PrivateUse SurrogateParagraphSeparator LineSeparatorSpace OtherSymbolModifierSymbolCurrencySymbol MathSymbolOtherPunctuation FinalQuote InitialQuoteClosePunctuationOpenPunctuationDashPunctuationConnectorPunctuation OtherNumber LetterNumber DecimalNumber EnclosingMarkSpacingCombiningMarkNonSpacingMark OtherLetterModifierLetterTitlecaseLetterLowercaseLetterUppercaseLetterFormatControlGHC.CharchrGHC.Show intToDigit showLitCharordStringtemplate-haskellLanguage.Haskell.TH.SyntaxnewName Language.Haskell.TH.Lib.InternalcharLstringLintegerLintPrimL wordPrimL floatPrimL doublePrimL rationalL stringPrimL charPrimLlitPvarPtupP unboxedTupP unboxedSumPconPinfixPtildePbangPasPwildPrecPlistPsigPviewPfieldPatclausevarEconElitEappEappTypeEinfixEinfixAppsectionLsectionRlamElamCaseE unboxedSumEcondEmultiIfEletEcaseEdoEcompEfromE fromThenEfromToE fromThenToElistEsigErecConErecUpdEstaticE unboundVarElabelEimplicitParamVarEmdoEfieldExpguardedBnormalBnormalGEpatGEbindSletSnoBindSparSrecSfunDvalDinstanceWithOverlapDsigDforImpDpragInlD pragSpecD pragSpecInlD pragSpecInstDpragAnnD tySynInstDinfixLDinfixRDinfixND roleAnnotD defaultSigDpatSynD patSynSigD pragCompleteDimplicitParamBindDkiSigDcxtnoSourceUnpackednesssourceNoUnpack sourceUnpacknoSourceStrictness sourceLazy sourceStrictnormalCrecCinfixCgadtCrecGadtCbangbangType varBangTypeunidir implBidir explBidir prefixPatSyn infixPatSyn recordPatSyn forallVisTvarTconTtupleT unboxedTupleT unboxedSumTarrowTlistTappTappKindT equalityTlitT promotedTpromotedTupleT promotedNilT promotedConsT wildCardTimplicitParamTinfixTnumTyLitstrTyLitnominalRrepresentationalRphantomRinferRvarKconKtupleKarrowKlistKappKinjectivityAnncCallstdCallcApiprim javaScriptunsafesafe interruptiblefunDepruleVar typedRuleVarvalueAnnotationtypeAnnotationmoduleAnnotationExpImplicitParamVarELabelE UnboundVarEStaticERecUpdERecConESigEListE ArithSeqECompEMDoEDoECaseELetEMultiIfECondE UnboxedSumE UnboxedTupETupELamCaseELamEParensEUInfixEInfixEAppTypeEAppELitEVarEConEMatchClauseQExpQDecQPatViewPSigPListPRecPWildPAsPBangPTildePParensPUInfixPInfixPConP UnboxedSumP UnboxedTupPTupPLitPVarPMatchQClauseQStmtQConQTypeQTypeImplicitParamT WildCardTLitT ConstraintTStarT PromotedConsT PromotedNilTPromotedTupleTListT EqualityTArrowT UnboxedSumT UnboxedTupleTTupleTParensTUInfixTInfixT PromotedTConTVarTSigTAppKindTAppTForallT ForallVisTDecImplicitParamBindD PatSynSigDPatSynD DefaultSigDStandaloneDerivD RoleAnnotDClosedTypeFamilyDOpenTypeFamilyD TySynInstD NewtypeInstD DataInstD DataFamilyDPragmaDInfixDForeignDKiSigDSigD InstanceDClassDTySynDNewtypeDDataDFunDValD BangTypeQ VarBangTypeQFieldExpFieldPatPatQ FieldPatQ FieldExpQFunDepPredPredQ TyVarBndrQDecsQ RuleBndrQ TySynEqnQTExpunTypeInjectivityAnnKindQOverlap IncoherentOverlaps Overlappable Overlapping DerivClauseQDerivStrategyQ stockStrategyanyclassStrategynewtypeStrategy viaStrategyghc-boot-th-8.10.2GHC.LanguageExtensions.Type ExtensionStandaloneKindSignaturesCUSKsImportQualifiedPost StarIsTypeQuantifiedConstraintsNumericUnderscoresEmptyDataDerivingMonadFailDesugaring StrictDataStrictTypeApplicationsStaticPointersNamedWildCardsPartialTypeSignaturesPatternSynonyms EmptyCaseOverloadedLabelsDuplicateRecordFieldsHexFloatLiteralsNegativeLiteralsBinaryLiterals MultiWayIf LambdaCaseTraditionalRecordSyntax RelaxedLayoutNondecreasingIndentationDatatypeContexts!AlternativeLayoutRuleTransitionalAlternativeLayoutRuleExplicitForAllPackageImportsExplicitNamespaces TypeOperatorsImpredicativeTypes RankNTypesLiberalTypeSynonyms PatternGuards TupleSectionsPostfixOperators RecursiveDoGeneralizedNewtypeDerivingMonadComprehensionsTransformListCompParallelListCompRoleAnnotationsKindSignaturesEmptyDataDecls MagicHashExistentialQuantification UnicodeSyntaxFunctionalDependenciesNullaryTypeClassesMultiParamTypeClassesConstrainedClassMethodsFlexibleInstancesFlexibleContextsTypeSynonymInstances DerivingViaDerivingStrategies DeriveLiftDeriveAnyClassDefaultSignatures DeriveGenericDeriveFoldableDeriveTraversable DeriveFunctorAutoDeriveTypeableDeriveDataTypeableStandaloneDeriving ApplicativeDo InstanceSigs DataKinds PolyKindsConstraintKindsRebindableSyntaxBlockArgumentsDoAndIfThenElseNPlusKPatterns GADTSyntaxGADTs ViewPatterns RecordPunsRecordWildCardsDisambiguateRecordFields NumDecimalsOverloadedListsOverloadedStrings TypeInTypeTypeFamilyDependencies TypeFamilies BangPatternsUnliftedNewtypes UnboxedSums UnboxedTuplesAllowAmbiguousTypesScopedTypeVariablesImplicitPreludeImplicitParams QuasiQuotesTemplateHaskellQuotesTemplateHaskellArrowsParallelArrays JavaScriptFFIGHCForeignImportPrimCApiFFIInterruptibleFFIUnliftedFFITypesForeignFunctionInterfaceExtendedDefaultRulesRelaxedPolyRecMonoLocalBinds MonoPatBindsMonomorphismRestrictionUndecidableSuperClassesIncoherentInstancesUndecidableInstancesCppOverlappingInstancesLanguage.Haskell.TH.Lib unboxedTupEtupEmkBytesstandaloneDerivWithStrategyD derivClausetyVarSigkindSignoSig constraintKstarKkindedTVplainTVsigTforallTforallCtySynEqnclosedTypeFamilyDopenTypeFamilyD dataFamilyD newtypeInstD dataInstD pragRuleDclassDnewtypeDdataDtySynD thisModuleappsE varStrictType strictTypeunpacked notStrictisStrictequalPclassPparensTuInfixTstandaloneDerivD pragLineD instanceDstringE arithSeqElam1EuInfixEparensEdynpatGnormalG fromThenToRfromToR fromThenRfromRparensPuInfixP bytesPrimLInfoQTExpQTyLitQCxtQBodyQGuardQRangeQSourceStrictnessQSourceUnpackednessQBangQ StrictTypeQVarStrictTypeQ PatSynDirQ PatSynArgsQFamilyResultSigQLanguage.Haskell.TH.Ppr pprParendTypepprPatpprLitpprExppprintPprpprppr_list defaultFixity maxPrecedenceunboxedSumTypeNameunboxedSumDataNameunboxedTupleTypeNameunboxedTupleDataName tupleTypeName tupleDataName nameSpace namePackage nameModulenameBase extsEnabled isExtEnabledrunIOlocation isInstancereifyConStrictness reifyModulereifyAnnotations reifyRolesreifyInstances reifyType reifyFixityreifylookupValueNamelookupTypeNamerecover reportWarning reportErrorreportrunQ NameSpaceLocloc_end loc_start loc_module loc_filename loc_packageInfoTyVarIVarIPatSynIDataConI PrimTyConIFamilyITyConIClassIClassOpI ModuleInfo ParentNameSumAltSumArityArityUnlifted InstanceDecFixityFixityDirectionInfixNInfixLInfixRLit CharPrimL BytesPrimL StringPrimL DoublePrimL FloatPrimL WordPrimLIntPrimL RationalLIntegerLCharLStringLBodyGuardedBNormalBGuardNormalGPatGStmtRecSParSNoBindSBindSLetSRange FromThenToRFromToRFromR FromThenR DerivClause DerivStrategy ViaStrategyNewtypeStrategy StockStrategyAnyclassStrategy PatSynTypeTypeFamilyHeadTySynEqnForeignImportFExportFCallconv JavaScriptPrimCApiCCallStdCallSafety InterruptibleUnsafeSafePragma CompletePLinePAnnPRulePSpecialiseInstPInlineP SpecialisePInline InlinableNoInline RuleMatchConLikeFunLikePhases BeforePhase AllPhases FromPhaseRuleBndrRuleVar TypedRuleVar AnnTargetValueAnnotationModuleAnnotationTypeAnnotationCxtSourceUnpackednessNoSourceUnpackedness SourceUnpackSourceNoUnpackSourceStrictnessNoSourceStrictness SourceLazy SourceStrictDecidedStrictness DecidedUnpack DecidedLazy DecidedStrictConRecGadtCGadtCForallCInfixCNormalCRecCBang PatSynDir ExplBidirUnidir ImplBidir PatSynArgs RecordPatSyn PrefixPatSyn InfixPatSyn TyVarBndrPlainTVKindedTVFamilyResultSigTyVarSigNoSigKindSigTyLitNumTyLitStrTyLitRoleInferRPhantomRNominalRRepresentationalR AnnLookupAnnLookupModule AnnLookupNameKind Data.TypeablemkFunTyData.Typeable.InternalTypeableTyContypeOf7typeOf6typeOf5typeOf4typeOf3typeOf2typeOf1 rnfTypeReptypeRepFingerprint typeRepTyCon typeRepArgs splitTyConApp funResultTygcast2gcast1gcasteqTcast showsTypeReptypeReptypeOfTypeReprnfTyContyConFingerprint tyConName tyConModule tyConPackage Data.ProxyProxyData.Type.Equality:~:Refl:~~:HReflShow Data.DynamicDynamic GHC.MaybeJustNothingGHC.Err undefinedshow GHC.ClassesEq==/=Ordcompare<=<-:>BoolFalseTruenot&&||IntGHC.Num+*idnegateabs