express (empty) → 0.1.0
raw patch · 73 files changed
+14892/−0 lines, 73 filesdep +basedep +expressdep +leanchecksetup-changed
Dependencies added: base, express, leancheck, template-haskell
Files
- .gitignore +46/−0
- .travis.yml +79/−0
- LICENSE +30/−0
- Makefile +131/−0
- README.md +316/−0
- Setup.hs +2/−0
- TODO.md +20/−0
- bench/compare.hs +22/−0
- bench/pairs.hs +14/−0
- bench/runtime/zero/bench/compare.runtime +1/−0
- bench/runtime/zero/bench/ord.runtime +1/−0
- bench/runtime/zero/bench/pairs.runtime +1/−0
- bench/runtime/zero/bench/tiers.runtime +1/−0
- bench/runtime/zero/eg/u-extrapolate.runtime +1/−0
- bench/runtime/zero/eg/u-speculate.runtime +1/−0
- bench/runtime/zero/versions +1/−0
- bench/tiers.hs +27/−0
- bench/versions +5/−0
- doc/express.svg +121/−0
- eg/u-extrapolate.hs +101/−0
- eg/u-speculate.hs +144/−0
- express.cabal +257/−0
- mk/All.hs +8/−0
- mk/Toplibs.hs +5/−0
- mk/depend.mk +814/−0
- mk/ghcdeps +49/−0
- mk/haddock-i +36/−0
- mk/haskell.mk +134/−0
- src/Data/Express.hs +259/−0
- src/Data/Express/Basic.hs +30/−0
- src/Data/Express/Canon.hs +234/−0
- src/Data/Express/Core.hs +1060/−0
- src/Data/Express/Express.hs +243/−0
- src/Data/Express/Express/Derive.hs +70/−0
- src/Data/Express/Fixtures.hs +1048/−0
- src/Data/Express/Fold.hs +133/−0
- src/Data/Express/Hole.hs +180/−0
- src/Data/Express/Instances.hs +359/−0
- src/Data/Express/Map.hs +245/−0
- src/Data/Express/Match.hs +118/−0
- src/Data/Express/Name.hs +248/−0
- src/Data/Express/Name/Derive.hs +54/−0
- src/Data/Express/Utils/List.hs +105/−0
- src/Data/Express/Utils/String.hs +171/−0
- src/Data/Express/Utils/TH.hs +290/−0
- src/Data/Express/Utils/Typeable.hs +121/−0
- stack-lts-11.yaml +17/−0
- stack.yaml +15/−0
- test/Test.hs +77/−0
- test/Test/ListableExpr.hs +285/−0
- test/canon.hs +119/−0
- test/core.hs +254/−0
- test/express-derive.hs +111/−0
- test/express.hs +109/−0
- test/fixtures.hs +173/−0
- test/fold.hs +34/−0
- test/hole.hs +30/−0
- test/instances.hs +51/−0
- test/listable.hs +79/−0
- test/main.hs +18/−0
- test/map.hs +101/−0
- test/match.hs +57/−0
- test/model/bench/compare.out +1001/−0
- test/model/bench/pairs.out +1001/−0
- test/model/bench/tiers.out +3624/−0
- test/model/eg/u-extrapolate.out +21/−0
- test/model/eg/u-speculate.out +45/−0
- test/name-derive.hs +56/−0
- test/name.hs +64/−0
- test/ord.hs +46/−0
- test/sdist +33/−0
- test/show.hs +82/−0
- test/utils.hs +53/−0
+ .gitignore view
@@ -0,0 +1,46 @@+.cabal-sandbox+cabal.sandbox.config+.stack-work+idx/+dist/+log/+*.swp+*.swo+*.swn+*.swm+*.o+*.hi+*.dyn_hi+*.dyn_o+TAGS+tags+eg/u-extrapolate+eg/u-speculate+bench/compare+bench/pairs+bench/tiers+test/canon+test/core+test/express+test/express-derive+test/fixtures+test/hole+test/instances+test/listable+test/main+test/map+test/match+test/name+test/name-derive+test/utils+test/fold+test/ord+test/show+doc/**/*.html+doc/**/*.css+doc/**/*.js+doc/**/*.png+doc/**/*.gif+doc/**/*.json+README.html+mk/toplibs
+ .travis.yml view
@@ -0,0 +1,79 @@+# .travis.yml file for Express+#+# Copyright: (c) 2017-2019 Rudy Matela+# License: 3-Clause BSD (see the file LICENSE)+# Maintainer: Rudy Matela <rudy@matela.com.br>++language: c # not really++notifications:+ email:+ on_failure: change++sudo: false++cache:+ directories:+ - $HOME/.ghc+ - $HOME/.cabal+ - $HOME/.stack++before_install:+- export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH+- ghc --version+- cabal --version+- rm -f ~/.cabal/config && cabal update+# Download and unpack the stack executable+# "Once Travis whitelists the stack.dev files," simply include stack in the+# addons section. -- https://docs.haskellstack.org/en/stable/travis_ci/+- mkdir -p ~/.local/bin+- export PATH=$HOME/.local/bin:$PATH+- travis_retry curl -L https://www.stackage.org/stack/linux-x86_64 | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack'+- stack config set system-ghc --global true+- stack --version+- cabal install leancheck++script:+- make && make test+- make haddock+- make test-sdist+- cabal test main --ghc-option=-O0+- stack $STACKR --no-terminal --skip-ghc-check test express:test:main --ghc-options=-O0++matrix:+ allow_failures:+ - ghc: 'head'+ include:+ - ghc: 'head'+ env: GHCVER=head CABALVER=head+ addons: {apt: {packages: [ghc-head, cabal-install-head], sources: hvr-ghc}}+ - ghc: '8.6'+ env: GHCVER=8.6.1 CABALVER=2.4+ addons: {apt: {packages: [ghc-8.6.1, cabal-install-2.4], sources: hvr-ghc}}+ - ghc: '8.4'+ env: GHCVER=8.4.4 CABALVER=2.2+ addons: {apt: {packages: [ghc-8.4.4, cabal-install-2.2], sources: hvr-ghc}}+ - ghc: '8.2'+ env: GHCVER=8.2.2 CABALVER=2.0+ addons: {apt: {packages: [ghc-8.2.2, cabal-install-2.0], sources: hvr-ghc}}+ - ghc: '8.0'+ env: GHCVER=8.0.2 CABALVER=1.24+ addons: {apt: {packages: [ghc-8.0.2, cabal-install-1.24], sources: hvr-ghc}}+ - ghc: '7.10'+ env: GHCVER=7.10.3 CABALVER=1.22 STACK_YAML=stack-lts-11.yaml+ addons: {apt: {packages: [ghc-7.10.3, cabal-install-1.22], sources: hvr-ghc}}+ # we only support stack with GHC >= 7.10+ - ghc: '7.8'+ env: GHCVER=7.8.4 CABALVER=1.18+ addons: {apt: {packages: [ghc-7.8.4, cabal-install-1.18], sources: hvr-ghc}}+ before_install:+ - export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH+ - ghc --version+ - cabal --version+ - rm -f ~/.cabal/config && cabal update+ - cabal install Cabal==1.18.*+ - cabal install leancheck+ script:+ - make && make test+ - make haddock HADDOCKFLAGS=+ - cabal test
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2019, Rudy Matela++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Rudy Matela nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Makefile view
@@ -0,0 +1,131 @@+# Makefile for express+#+# Copyright: (c) 2015-2018 Rudy Matela+# License: 3-Clause BSD (see the file LICENSE)+# Maintainer: Rudy Matela <rudy@matela.com.br>+TESTS = \+ test/main \+ test/core \+ test/map \+ test/instances \+ test/fixtures \+ test/express \+ test/express-derive \+ test/name \+ test/name-derive \+ test/utils \+ test/canon \+ test/match \+ test/hole \+ test/fold \+ test/show \+ test/ord \+ test/listable+EGS =+BENCHS = \+ eg/u-extrapolate \+ eg/u-speculate \+ bench/compare \+ bench/pairs \+ bench/tiers \+ $(EGS)+GHCIMPORTDIRS = src:test+GHCFLAGS = -O2 $(shell grep -q "Arch Linux" /etc/lsb-release && echo -dynamic)+HADDOCKFLAGS = --no-print-missing-docs+RUNPARAMETERS =+LIB_DEPS = base template-haskell++all: mk/toplibs++all-all: mk/All.o++test: $(patsubst %,%.run,$(TESTS)) test-sdist diff-test++slow-test: RUNPARAMETERS=50400+slow-test: test++%.run: %+ ./$< $(RUNPARAMETERS)++.PHONY: bench+bench: $(patsubst %,%.bench,$(BENCHS))+ @mkdir -p bench/runtime/$$HOSTNAME+ ./bench/versions | tee bench/runtime/$$HOSTNAME/versions++.PHONY: %.bench+%.bench: %+ @mkdir -p bench/runtime/$$HOSTNAME/$<+ @printf "%-18s " $<+ @/usr/bin/time -f%e ./$< 2>&1 >/dev/null | tee bench/runtime/$$HOSTNAME/$<.runtime++clean: clean-hi-o clean-haddock+ rm -f $(TESTS) $(BENCHS) $(EGS) mk/toplibs++ghci: mk/All.ghci++install:+ @echo "use \`cabal install' instead"++test-sdist:+ ./test/sdist++test-via-cabal:+ cabal test++test-via-stack:+ stack test++diff-test: $(patsubst %,%.diff-test,$(BENCHS))++update-diff-test: $(patsubst %,%.update-diff-test,$(BENCHS))++%.diff-test: %+ ./$< | diff -rud test/model/$<.out -++%.update-diff-test: %+ ./$< > test/model/$<.out++test-via-everything: test test-via-cabal test-via-stack++legacy-test: # needs ghc-8.0 .. ghc-7.8 installed as such+ make clean && make test GHC=ghc-8.2 GHCFLAGS="-Werror -dynamic"+ make clean && make test GHC=ghc-8.0 GHCFLAGS="-Werror -dynamic"+ make clean && make test GHC=ghc-7.10 GHCFLAGS="-Werror -dynamic"+ make clean && make test GHC=ghc-7.8 GHCFLAGS="-Werror -dynamic"+ make clean && make test++legacy-test-via-cabal: # needs similarly named cabal wrappers+ cabal clean && cabal-ghc-8.2 configure && cabal-ghc-8.2 test+ cabal clean && cabal-ghc-8.0 configure && cabal-ghc-8.0 test+ cabal clean && cabal-ghc-7.10 configure && cabal-ghc-7.10 test+ cabal clean && cabal-ghc-7.8 configure && cabal-ghc-7.8 test+ cabal clean && cabal test++prepare:+ cabal update && cabal install leancheck++prepare-legacy-test:+ cabal-ghc-8.2 update && cabal-ghc-8.2 install leancheck+ cabal-ghc-8.0 update && cabal-ghc-8.0 install leancheck+ cabal-ghc-7.10 update && cabal-ghc-7.10 install leancheck+ cabal-ghc-7.8 update && cabal-ghc-7.8 install leancheck++hlint:+ hlint \+ --ignore "Use import/export shortcut" \+ --ignore "Redundant bracket" \+ .++markdown: README.html++%.html: %.md+ pandoc $< -o $@++# NOTE: (very hacky!) the following target allows parallel compilation (-jN) of+# eg and test programs so long as they don't share dependencies _not_ stored+# in src/ and test/. Runnable binaries should depend on mk/toplibs instead of+# actual Haskell source files+mk/toplibs: mk/Toplibs.o+ touch mk/toplibs++include mk/haskell.mk
+ README.md view
@@ -0,0 +1,316 @@+Express+=======++[![Express's Build Status][build-status]][build-log]+[![Express on Hackage][hackage-version]][express-on-hackage]+[![Express on Stackage LTS][stackage-lts-badge]][express-on-stackage-lts]+[![Express on Stackage Nightly][stackage-nightly-badge]][express-on-stackage-nightly]++![Express logo][express-logo]+++Express is a library for manipulating dynamically typed Haskell expressions.+It's like [`Data.Dynamic`] but with support for encoding applications and+variables.++It provides the [`Expr`] type and over a hundred functions for+building, evaluating, comparing, folding, canonicalizing and matching+[`Expr`]s. See [Express's Haddock documentation] for more details.++This library has been used successfully in the implementation of+[Speculate] and [Extrapolate].+++Installing+----------++To install the latest Express version from Hackage, just run:++ $ cabal update+ $ cabal install express+++Example 1: heterogeneous lists+------------------------------++Like with [`Data.Dynamic`], we can use Express to create heterogeneous lists.++For types that are [`Show`] instances, we can use [`val`] to encode values as [`Expr`]s.+Here, we use applications of [`val`] to create a heterogeneous list:++ > let xs = [val False, val True, val (1::Int), val (2::Int), val (3::Integer), val "123"]+ > :t xs+ xs :: [Expr]+ > xs+ [ False :: Bool+ , True :: Bool+ , 1 :: Int+ , 2 :: Int+ , 3 :: Integer+ , "123" :: [Char]+ ]++We can then apply [`evaluate`] to select values of different types:++ > import Data.Maybe+ > mapMaybe evaluate xs :: [Bool]+ [False,True]+ > mapMaybe evaluate xs :: [Int]+ [1,2]+ > mapMaybe evaluate xs :: [Integer]+ [3]+ > mapMaybe evaluate xs :: [String]+ ["123"]+++Example 2: listing applications+-------------------------------++Carrying on from Example 1, we define an heterogeneous list of functions+encoded as [`Expr`]s:++ > let fs = [value "not" not, value "&&" (&&), value "abs" (abs :: Int -> Int)]+ > :t fs+ fs :: [Expr]++Using [`$$`] we list the type correct applications of functions in `fs` to+values in `xs`.++ > catMaybes [f $$ x | f <- fs, x <- xs]+ [ not False :: Bool+ , not True :: Bool+ , (False &&) :: Bool -> Bool+ , (True &&) :: Bool -> Bool+ , abs 1 :: Int+ , abs 2 :: Int+ ]++Example 3: u-Extrapolate+------------------------++[u-Extrapolate] is a property-based testing property-based testing library+capable of generalizing counter-examples. It's implementation has under 40+lines of code. Besides, using Express to encode expressions, it uses+[LeanCheck] for generating test values.++ import Data.Express+ import Test.LeanCheck hiding (counterExample, check)++Given a maximum number of tests and a property, the following `counterExample`+function returns either `Nothing` when tests pass or `Just` a counterexample+encoded as an [`Expr`].++ counterExample :: (Listable a, Express a) => Int -> (a -> Bool) -> Maybe Expr+ counterExample maxTests prop = listToMaybe+ [expr x | x <- take maxTests list, not (prop x)]++Examples (REPL):++ > counterExample 100 (\(x,y) -> x + y == y + x)+ Nothing+ > counterExample 100 (\x -> x == x + x)+ Just (1 :: Integer)+ > counterExample 100 (\xs -> nub xs == (xs :: [Int]))+ Just ([0,0] :: [Int])++Before moving on to generalize counterexamples, we need a way to compute ground+expressions from an expression with variables. For that, we will use `grounds`+and `tiersFor`:++ grounds :: Expr -> [Expr]+ grounds e = map (e //-)+ . concat+ $ products [mapT ((,) v) (tiersFor v) | v <- nubVars e]++ tiersFor :: Expr -> [[Expr]]+ tiersFor e = case show (typ e) of+ "Int" -> mapT val (tiers `asTypeOf` [[undefined :: Int]])+ "Bool" -> mapT val (tiers `asTypeOf` [[undefined :: Bool]])+ "[Int]" -> mapT val (tiers `asTypeOf` [[undefined :: [Int]]])+ "[Bool]" -> mapT val (tiers `asTypeOf` [[undefined :: [Bool]]])+ _ -> []++Above, we restrict ourselves to `Int`, `Bool`, `[Int]` and `[Bool]` as test+types. So we can now compute the grounds of an expression with variables:++ > grounds (value "not" not :$ var "p" (undefined :: Bool))+ [ not False :: Bool+ , not True :: Bool+ ]+ > grounds (value "&&" (&&) :$ var "p" (undefined :: Bool) :$ var "q" (undefined :: Bool))+ [ False && False :: Bool+ , False && True :: Bool+ , True && False :: Bool+ , True && True :: Bool+ ]++To compute candidate generalizations from a given counter-example, we use the+following function:++ candidateGeneralizations :: Expr -> [Expr]+ candidateGeneralizations = map canonicalize+ . concatMap canonicalVariations+ . gen+ where+ gen e@(e1 :$ e2) =+ [holeAsTypeOf e | isListable e]+ ++ [g1 :$ g2 | g1 <- gen e1, g2 <- gen e2]+ ++ map (:$ e2) (gen e1)+ ++ map (e1 :$) (gen e2)+ gen e+ | isVar e = []+ | otherwise = [holeAsTypeOf e | isListable e]+ isListable = not . null . tiersFor++The need for `isListable` above makes sure we only replace by variables what we+can enumerate. Our candidate generalizations are listed in non-increasing+order of generality:++ > candidateGeneralizations (value "not" not :$ val False)+ [ p :: Bool+ , not p :: Bool+ ]+ Prelude> candidateGeneralizations (value "||" (||) :$ val False :$ val True)+ [ p :: Bool+ , p || q :: Bool+ , p || p :: Bool+ , p || True :: Bool+ , False || p :: Bool+ ]++For a given maximum number of tests, property and counter-example, the+following function returns a counter-example generalization if one is found.+It goes through the list of candidate generalizations and returns the first for+which all tests _fail_.++ counterExampleGeneralization :: Express a => Int -> (a -> Bool) -> Expr -> Maybe Expr+ counterExampleGeneralization maxTests prop e = listToMaybe+ [g | g <- candidateGeneralizations e+ , all (not . prop . evl) (take maxTests $ grounds g)]++We can finally define our `check` function, that will test a property and+report a counterexample and a generalization when either are found.++ check :: (Listable a, Express a) => (a -> Bool) -> IO ()+ check prop = putStrLn $ case counterExample 500 prop of+ Nothing -> "+++ Tests passed.\n"+ Just ce -> "*** Falsified, counterexample: " ++ show ce+ ++ case counterExampleGeneralization 500 prop ce of+ Nothing -> ""+ Just g -> "\n generalization: " ++ show g+ ++ "\n"++Now we can find counterexamples and their generalizations:++ > check $ \xs -> sort (sort xs :: [Int]) == sort xs+ +++ Tests passed.++ > check $ \xs -> length (nub xs :: [Int]) == length xs+ *** Falsified, counterexample: [0,0] :: [Int]+ generalization: x:x:xs :: [Int]++ > check $ \x -> x == x + (1 :: Int)+ *** Falsified, counterexample: 0 :: Int+ generalization: x :: Int++ > check $ \(x,y) -> x /= (y :: Int)+ *** Falsified, counterexample: (0,0) :: (Int,Int)+ generalization: (x,x) :: (Int,Int)++[u-Extrapolate] has some limitations:++* it only supports properties with one argument (uncurried);+* it only supports generalization of `Int`, `Bool`, `[Int]` and `[Bool]` values;+* there is no way to configure the number of test arguments.++Please see [Extrapolate] for a full-featured version without the above+limitations and with support for conditional generalizations.+++Example 4: u-Speculate+----------------------++Using Express, it takes less than 70 lines of code to define a function+`speculateAbout` that conjectures equations about a set of functions based on+the results of testing:++ > speculateAbout [hole (undefined :: Bool), val False, val True, value "not" not]+ [ not False == True :: Bool+ , not True == False :: Bool+ , not (not p) == p :: Bool+ ]++ > speculateAbout+ > [ hole (undefined :: Int)+ > , hole (undefined :: [Int])+ > , val ([] :: [Int])+ > , value ":" ((:) :: Int -> [Int] -> [Int])+ > , value "++" ((++) :: [Int] -> [Int] -> [Int])+ > , value "sort" (sort :: [Int] -> [Int])+ > ]+ [ sort [] == [] :: Bool+ , xs ++ [] == xs :: Bool+ , [] ++ xs == xs :: Bool+ , sort (sort xs) == sort xs :: Bool+ , sort [x] == [x] :: Bool+ , [x] ++ xs == x:xs :: Bool+ , sort (xs ++ ys) == sort (ys ++ xs) :: Bool+ , sort (x:sort xs) == sort (x:xs) :: Bool+ , sort (xs ++ sort ys) == sort (xs ++ ys) :: Bool+ , sort (sort xs ++ ys) == sort (xs ++ ys) :: Bool+ , (x:xs) ++ ys == x:(xs ++ ys) :: Bool+ , (xs ++ ys) ++ zs == xs ++ (ys ++ zs) :: Bool+ ]++Please see the [u-Speculate] example in the [eg](eg) folder for the full code+of `speculateAbout`.++[u-Speculate] has some limitations:++* it sometimes prints redundant equations;+* although it usually runs quickly with less than 6 symbols,+ runtime is exponential with the number of symbols given,+ providing it with more than a dozen symbols can make it run for several+ minutes or hours;+* there is no way to configure the size limit of reported equations;+* it only supports variables of `Int`, `Bool`, `[Int]`, and `[Bool]` types.++Please see [Speculate] for a full-featured version without the above+limitations.+++Further reading+---------------++For a detailed documentation, please see [Express's Haddock documentation].++For more examples, see the [eg](eg) and [bench](bench) folders.+++[Express's Haddock documentation]: https://hackage.haskell.org/package/express/docs/Data-Express.html++[`Expr`]: https://hackage.haskell.org/package/express/docs/Data-Express.html#t:val+[`val`]: https://hackage.haskell.org/package/express/docs/Data-Express.html#v:val+[`evaluate`]: https://hackage.haskell.org/package/express/docs/Data-Express.html#v:evaluate+[`$$`]: https://hackage.haskell.org/package/express/docs/Data-Express.html#v:-36--36-+[`Show`]: https://hackage.haskell.org/package/base/docs/Prelude.html#t:Show+[`Data.Dynamic`]: https://hackage.haskell.org/package/base/docs/Data-Dynamic.html++[LeanCheck]: https://hackage.haskell.org/package/leancheck+[Extrapolate]: https://hackage.haskell.org/package/extrapolate+[Speculate]: https://hackage.haskell.org/package/speculate++[u-Speculate]: eg/u-speculate.hs+[u-Extrapolate]: eg/u-extrapolate.hs++[express-logo]: https://github.com/rudymatela/express/raw/master/doc/express.svg?sanitize=true++[build-status]: https://travis-ci.org/rudymatela/express.svg?branch=master+[build-log]: https://travis-ci.org/rudymatela/express+[hackage-version]: https://img.shields.io/hackage/v/express.svg+[express-on-hackage]: https://hackage.haskell.org/package/express+[stackage-lts-badge]: https://stackage.org/package/express/badge/lts+[stackage-nightly-badge]: https://stackage.org/package/express/badge/nightly+[express-on-stackage]: https://stackage.org/package/express+[express-on-stackage-lts]: https://stackage.org/lts/package/express+[express-on-stackage-nightly]: https://stackage.org/nightly/package/express
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ TODO.md view
@@ -0,0 +1,20 @@+TO DO list for express+======================++Here is a list of things TO DO for express:++* release on Hackage -- this should coincide with a new release for both+ Speculate and Extrapolate.+++* review `Data.Express` haddock++* document the `Instances` module++* test the `Instances` module++* sweep occurrences of `TODO:` throughout source files++* Document `test/Test.ListableExpr` module thoroughly;++
+ bench/compare.hs view
@@ -0,0 +1,22 @@+-- ord.hs -- prints results of the Ord Expr's instance+--+-- Copyright (c) 2019 Rudy Matela.+-- Distributed under the 3-Clause BSD licence (see the file LICENSE).+import Test+import System.Environment (getArgs)++main :: IO ()+main = do+ as <- getArgs+ let n = case as of+ [] -> 1000+ (n:_) -> read n+ putStrLn . unlines . map showCompare $ take n (list :: [(Expr,Expr)])+ where+ showCompare (e1,e2) = concat+ [ show e1+ , " `compare` "+ , show e2+ , " = "+ , show $ e1 `compare` e2+ ]
+ bench/pairs.hs view
@@ -0,0 +1,14 @@+-- pairs.hs -- a thousand pairs of expressions+--+-- Copyright (c) 2019 Rudy Matela.+-- Distributed under the 3-Clause BSD licence (see the file LICENSE).+import Test+import System.Environment (getArgs)++main :: IO ()+main = do+ as <- getArgs+ let n = case as of+ [] -> 1000+ (n:_) -> read n+ putStrLn . unlines . map show $ take n (list :: [(Expr,Expr)])
+ bench/runtime/zero/bench/compare.runtime view
@@ -0,0 +1,1 @@+0.01
+ bench/runtime/zero/bench/ord.runtime view
@@ -0,0 +1,1 @@+0.00
+ bench/runtime/zero/bench/pairs.runtime view
@@ -0,0 +1,1 @@+0.01
+ bench/runtime/zero/bench/tiers.runtime view
@@ -0,0 +1,1 @@+0.21
+ bench/runtime/zero/eg/u-extrapolate.runtime view
@@ -0,0 +1,1 @@+0.01
+ bench/runtime/zero/eg/u-speculate.runtime view
@@ -0,0 +1,1 @@+0.33
+ bench/runtime/zero/versions view
@@ -0,0 +1,1 @@+GHC 8.6.5
+ bench/tiers.hs view
@@ -0,0 +1,27 @@+-- tiers.hs -- prints tiers of expressions+--+-- Copyright (c) 2019 Rudy Matela.+-- Distributed under the 3-Clause BSD licence (see the file LICENSE).+import Test+import Data.List (intercalate, nub)+import Test.LeanCheck.Tiers (showTiers)+import Data.Express.Utils.List++showDotsLongerThan :: Show a => Int -> [a] -> String+showDotsLongerThan n xs = "["+ ++ intercalate "," (dotsLongerThan n $ map show xs)+ ++ "]"+ where+ dotsLongerThan n xs = take n xs ++ ["..." | not . null $ drop n xs]++printTiers :: Show a => Int -> [[a]] -> IO ()+printTiers n = putStrLn . init . unlines . map (" " ++) . lines . showTiers n++main :: IO ()+main = do+ putStrLn $ "isNub (list :: [Expr]) = "+ ++ show (isNub (take 5040 list :: [Expr]))+ putStrLn $ "map length (tiers :: [[ Expr ]]) = "+ ++ showDotsLongerThan 9 (map length (tiers :: [[Expr]]))+ putStrLn $ "tiers :: [[ Expr ]] ="+ printTiers 7 (tiers :: [[Expr]])
+ bench/versions view
@@ -0,0 +1,5 @@+#!/bin/bash+get-ghc-v() {+ ghc --version | sed -e "s/.* version/GHC/"+}+get-ghc-v
+ doc/express.svg view
@@ -0,0 +1,121 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="75mm"+ height="60mm"+ viewBox="0 0 74.999998 60.000001"+ version="1.1"+ id="svg857"+ inkscape:version="0.92.4 5da689c313, 2019-01-14"+ sodipodi:docname="express.svg">+ <title+ id="title867">Express</title>+ <defs+ id="defs851">+ <clipPath+ id="clip1">+ <path+ inkscape:connector-curvature="0"+ d="M 0,340.15625 H 481.89062 V 0 H 0 Z m 0,0"+ id="path2" />+ </clipPath>+ </defs>+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0"+ inkscape:pageshadow="2"+ inkscape:zoom="0.70710678"+ inkscape:cx="-293.54885"+ inkscape:cy="190.13572"+ inkscape:document-units="mm"+ inkscape:current-layer="layer1"+ showgrid="false"+ fit-margin-top="0"+ fit-margin-left="0"+ fit-margin-right="0"+ fit-margin-bottom="0"+ inkscape:window-width="1630"+ inkscape:window-height="1063"+ inkscape:window-x="1366"+ inkscape:window-y="15"+ inkscape:window-maximized="0" />+ <metadata+ id="metadata854">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title>Express</dc:title>+ <cc:license+ rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />+ <dc:date>2019-08-03</dc:date>+ <dc:creator>+ <cc:Agent>+ <dc:title>Rudy Matela</dc:title>+ </cc:Agent>+ </dc:creator>+ <dc:source>https://github.com/rudymatela/express</dc:source>+ <dc:subject>+ <rdf:Bag>+ <rdf:li>Express</rdf:li>+ <rdf:li>Haskell</rdf:li>+ <rdf:li>logo</rdf:li>+ </rdf:Bag>+ </dc:subject>+ <dc:description>Express's logo. An X is seen in blue intersected with a lambda sign.++The proportions are based on the beautiful proportions of the Thompson-Wheeler Haskell logo (2009).</dc:description>+ </cc:Work>+ <cc:License+ rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">+ <cc:permits+ rdf:resource="http://creativecommons.org/ns#Reproduction" />+ <cc:permits+ rdf:resource="http://creativecommons.org/ns#Distribution" />+ <cc:requires+ rdf:resource="http://creativecommons.org/ns#Notice" />+ <cc:requires+ rdf:resource="http://creativecommons.org/ns#Attribution" />+ <cc:permits+ rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />+ <cc:requires+ rdf:resource="http://creativecommons.org/ns#ShareAlike" />+ </cc:License>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="Layer 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(277.11863,-172.26764)">+ <path+ style="clip-rule:nonzero;fill:#7f99b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.17638953"+ d="m -217.11863,172.26764 -39.99977,59.99992 h 14.99992 l 39.99977,-59.99992 z"+ id="path9-3"+ inkscape:connector-curvature="0"+ sodipodi:nodetypes="ccccc" />+ <path+ inkscape:connector-curvature="0"+ id="path9"+ d="m -257.1184,232.26764 20.00023,-30 -20.00023,-30 h 15 l 39.99977,60 h -15 l -12.49954,-18.74965 -12.50023,18.74965 z m 0,0"+ style="clip-rule:nonzero;fill:#4c6680;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.17638952" />+ <path+ style="clip-rule:nonzero;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.1763895"+ d="m -277.11863,232.26764 20.00023,-30 -20.00023,-30 h 15 l 20.00023,30 -20.00023,30 z m 0,0"+ id="path7"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ eg/u-extrapolate.hs view
@@ -0,0 +1,101 @@+-- u-extrapolate.hs -- micro Extrapolate / Extrapolite+--+-- Copyright (c) 2019 Rudy Matela.+-- Distributed under the 3-Clause BSD licence (see the file LICENSE).+--+-- A small property-based testing library capable of generalizing+-- counterexamples implemented in under 50 lines of code.+--+-- This example works like other property-based testing libraries+-- like QuickCheck, LeanCheck or SmallCheck:+--+-- When given a property, it will test it for 500 test arguments.+-- If no counterexample is found, "tests passed" is reported.+-- If a counterexample is found, it is reported.+--+-- However, when a counterexample is found, this program will try to generalize+-- it by replacing subexpressions to variables. If a generalization that+-- _fails_ 500 tests is found, it is reported.+--+-- Limitations:+--+-- * this only supports properties with one argument (uncurried).+-- * this only supports generalization of Int, Bool, [Int] and [Bool] values.+-- * there is no way to configure the number of test arguments.+--+-- Please see Extrapolate for a full-featured version:+--+-- https://github.com/rudymatela/extrapolate+import Data.List+import Data.Maybe+import Data.Express+import Test.LeanCheck hiding (counterExample, check)++main :: IO ()+main = do+ putStrLn "sort . sort = sort"+ check $ \xs -> sort (sort xs :: [Int]) == sort xs++ putStrLn "length . nub = length (incorrect when there are repeated elements)"+ check $ \xs -> length (nub xs :: [Int]) == length xs++ putStrLn "\\(x,y) -> x + y == y + x"+ check $ \(x,y) -> x + y == y + (x :: Int)++ putStrLn "\\x -> x == x + 1 (always incorrect)"+ check $ \x -> x == x + (1 :: Int)++ putStrLn "\\(x,y) -> x + y == x + x (incorrect)"+ check $ \(x,y) -> x + y == x + (x :: Int)++ putStrLn "\\(x,y) -> x /= y (incorrect whenever x and y are equal)"+ check $ \(x,y) -> x /= (y :: Int)+++check :: (Listable a, Express a) => (a -> Bool) -> IO ()+check prop = putStrLn $ case counterExample 500 prop of+ Nothing -> "+++ Tests passed.\n"+ Just ce -> "*** Falsified, counterexample: " ++ show ce+ ++ case counterExampleGeneralization 500 prop ce of+ Nothing -> ""+ Just g -> "\n generalization: " ++ show g+ ++ "\n"+++counterExample :: (Listable a, Express a) => Int -> (a -> Bool) -> Maybe Expr+counterExample maxTests prop = listToMaybe+ [expr x | x <- take maxTests list, not (prop x)]++counterExampleGeneralization :: Express a => Int -> (a -> Bool) -> Expr -> Maybe Expr+counterExampleGeneralization maxTests prop e = listToMaybe+ [g | g <- candidateGeneralizations e+ , all (not . prop . evl) (take maxTests $ grounds g)]+++candidateGeneralizations :: Expr -> [Expr]+candidateGeneralizations = map canonicalize+ . concatMap canonicalVariations+ . gen+ where+ gen e@(e1 :$ e2) =+ [holeAsTypeOf e | isListable e]+ ++ [g1 :$ g2 | g1 <- gen e1, g2 <- gen e2]+ ++ map (:$ e2) (gen e1)+ ++ map (e1 :$) (gen e2)+ gen e+ | isVar e = []+ | otherwise = [holeAsTypeOf e | isListable e]+ isListable = not . null . tiersFor++grounds :: Expr -> [Expr]+grounds e = map (e //-)+ . concat+ $ products [mapT ((,) v) (tiersFor v) | v <- nubVars e]++tiersFor :: Expr -> [[Expr]]+tiersFor e = case show (typ e) of+ "Int" -> mapT val (tiers `asTypeOf` [[undefined :: Int]])+ "Bool" -> mapT val (tiers `asTypeOf` [[undefined :: Bool]])+ "[Int]" -> mapT val (tiers `asTypeOf` [[undefined :: [Int]]])+ "[Bool]" -> mapT val (tiers `asTypeOf` [[undefined :: [Bool]]])+ _ -> []
+ eg/u-speculate.hs view
@@ -0,0 +1,144 @@+-- u-extrapolate.hs -- micro Speculate / Speculite+--+-- Copyright (c) 2019 Rudy Matela.+-- Distributed under the 3-Clause BSD licence (see the file LICENSE).+--+-- A small library capable of conjecturing laws about Haskell functions+-- implemented in under 70 lines of code.+--+-- This works like the equation conjecturing tools Speculate or QuickSpec,+-- combining expressions to form equations,+-- reporting any equations that passes 60 tests.+-- Redundant equations are then pruned using simple rules.+--+-- Limitations:+--+-- * even with pruning, this program still prints some redundant rules;+-- * there is no way to configure maximum number of tests to consider an+-- equation true;+-- * runtime is exponential as you add more symbols to Speculate about.+--+-- Please see Speculate for a full featured version:+--+-- https://github.com/rudymatela/speculate+import Data.List+import Data.Maybe+import Data.Express+import Test.LeanCheck++main :: IO ()+main = do+ printEquationsAbout+ [ hole (undefined :: Int)+ , val (0 :: Int)+ , value "+" ((+) :: Int -> Int -> Int)+ , value "abs" (abs :: Int -> Int)+ ]++ printEquationsAbout+ [ hole (undefined :: Bool)+ , val False+ , val True+ , value "not" not+ ]++ printEquationsAbout+ [ hole (undefined :: Int)+ , hole (undefined :: [Int])+ , val ([] :: [Int])+ , value ":" ((:) :: Int -> [Int] -> [Int])+ , value "++" ((++) :: [Int] -> [Int] -> [Int])+ , value "sort" (sort :: [Int] -> [Int])+ ]++ {-+ printEquationsAbout+ [ hole (undefined :: Bool)+ , hole (undefined :: [Bool])+ , val True+ , val ([] :: [Bool])+ , value "foldr" (foldr :: (Bool -> Bool -> Bool) -> Bool -> [Bool] -> Bool)+ , value "&&" (&&)+ , value "and" (and :: [Bool] -> Bool)+ ]+ -}++printEquationsAbout :: [Expr] -> IO ()+printEquationsAbout es = do+ putStrLn $ "Equations about " ++ intercalate ", " (map showExpr es) ++ ":"+ putStrLn . unlines . map showEq $ speculateAbout es+ where+ showEq eq = showExpr (lhs eq) ++ " = " ++ showExpr (rhs eq)++speculateAbout :: [Expr] -> [Expr]+speculateAbout = discardLater hasRewrite+ . discardLaterInstances+ . concatMap trueCanonicalVariations+ . discardLaterInstances+ . sort+ . filter isTrue+ . candidateEquationsFrom+ where+ hasRewrite e1 e2 = isRule e2 && e1 `hasInstanceOf` lhs e2++trueCanonicalVariations :: Expr -> [Expr]+trueCanonicalVariations = discardLaterInstances+ . filter isTrue+ . filter isntIdentity+ . canonicalVariations++discardLaterInstances :: [Expr] -> [Expr]+discardLaterInstances = discardLater (\e1 e2 -> isntIdentity e2 && e1 `isInstanceOf` e2)++candidateEquationsFrom :: [Expr] -> [Expr]+candidateEquationsFrom es' = [e1 -==- e2 | e1 <- es, e2 <- es, e1 >= e2]+ where+ es = candidateExprsFrom es'++candidateExprsFrom :: [Expr] -> [Expr]+candidateExprsFrom = concat . take 5 . expressionsT+ where+ expressionsT ds = [ds] \/ (delay $ productMaybeWith ($$) es es)+ where+ es = expressionsT ds++isTrue :: Expr -> Bool+isTrue = all (eval False) . take 60 . grounds++grounds :: Expr -> [Expr]+grounds e = map (e //-) . concat+ $ products [mapT ((,) v) (tiersFor v) | v <- nubVars e]++tiersFor :: Expr -> [[Expr]]+tiersFor e = case show (typ e) of+ "Int" -> mapT val (tiers `asTypeOf` [[undefined :: Int]])+ "Bool" -> mapT val (tiers `asTypeOf` [[undefined :: Bool]])+ "[Int]" -> mapT val (tiers `asTypeOf` [[undefined :: [Int]]])+ "[Bool]" -> mapT val (tiers `asTypeOf` [[undefined :: [Bool]]])+ _ -> []++(-==-) :: Expr -> Expr -> Expr+ex -==- ey = headOr (val False) . map (:$ ey) $ mapMaybe ($$ ex)+ [ value "==" ((==) :: Int -> Int -> Bool)+ , value "==" ((==) :: Bool -> Bool -> Bool)+ , value "==" ((==) :: [Int] -> [Int] -> Bool)+ , value "==" ((==) :: [Bool] -> [Bool] -> Bool)+ ]+ where+ headOr x [] = x+ headOr _ (x:_) = x++lhs, rhs :: Expr -> Expr+lhs (((Value "==" _) :$ e) :$ _) = e+rhs (((Value "==" _) :$ _) :$ e) = e++isntIdentity, isRule :: Expr -> Bool+isntIdentity eq = lhs eq /= rhs eq+isRule eq = size (lhs eq) > size (rhs eq)++discardLater :: (a -> a -> Bool) -> [a] -> [a]+discardLater (?) = d+ where+ d [] = []+ d (x:xs) = x : d (discard (? x) xs)+ discard p = filter (not . p)
+ express.cabal view
@@ -0,0 +1,257 @@+-- Cabal file for express+name: express+version: 0.1.0+synopsis: Express+description:+ Express is a library for manipulating dynamically typed Haskell expressions.+ It's like @ Data.Dynamic @ but with support for encoding applications and+ variables.+ .+ It provides the @ Expr @ type and over a hundred functions for+ building, evaluating, comparing, folding, canonicalizing and matching+ @ Expr @s. See the README and Haddock documentation for more details.+++homepage: https://github.com/rudymatela/express#readme+license: BSD3+license-file: LICENSE+author: Rudy Matela <rudy@matela.com.br>+maintainer: Rudy Matela <rudy@matela.com.br>+category: Testing+build-type: Simple+cabal-version: 1.18++extra-doc-files: README.md+ , TODO.md+ , doc/express.svg+extra-source-files: .gitignore+ , .travis.yml+ , Makefile+ , mk/depend.mk+ , mk/haskell.mk+ , mk/ghcdeps+ , mk/haddock-i+ , mk/All.hs+ , mk/Toplibs.hs+ , stack.yaml+ , stack-lts-11.yaml+ , test/sdist+ , test/model/bench/*.out+ , test/model/eg/*.out+ , bench/versions+ , bench/runtime/zero/versions+ , bench/runtime/zero/bench/*.runtime+ , bench/runtime/zero/eg/*.runtime+tested-with: GHC==8.6+ , GHC==8.4+ , GHC==8.2+ , GHC==8.0+ , GHC==7.10+ , GHC==7.8+++source-repository head+ type: git+ location: https://github.com/rudymatela/express++source-repository this+ type: git+ location: https://github.com/rudymatela/express+ tag: v0.1.0++library+ exposed-modules: Data.Express+ , Data.Express.Core+ , Data.Express.Basic+ , Data.Express.Map+ , Data.Express.Express+ , Data.Express.Express.Derive+ , Data.Express.Fixtures+ , Data.Express.Fold+ , Data.Express.Hole+ , Data.Express.Instances+ , Data.Express.Name+ , Data.Express.Name.Derive+ , Data.Express.Canon+ , Data.Express.Match+ , Data.Express.Utils.List+ , Data.Express.Utils.String+ , Data.Express.Utils.Typeable+ , Data.Express.Utils.TH+ hs-source-dirs: src+ build-depends: base >= 4 && < 5, template-haskell+ default-language: Haskell2010++test-suite main+ type: exitcode-stdio-1.0+ main-is: main.hs+ hs-source-dirs: test+ other-modules: Test, Test.ListableExpr+ build-depends: base >= 4 && < 5, express, leancheck >= 0.8+ default-language: Haskell2010++test-suite core+ type: exitcode-stdio-1.0+ main-is: core.hs+ hs-source-dirs: test+ other-modules: Test, Test.ListableExpr+ build-depends: base >= 4 && < 5, express, leancheck >= 0.8+ default-language: Haskell2010++test-suite canon+ type: exitcode-stdio-1.0+ main-is: canon.hs+ hs-source-dirs: test+ other-modules: Test, Test.ListableExpr+ build-depends: base >= 4 && < 5, express, leancheck >= 0.8+ default-language: Haskell2010++test-suite hole+ type: exitcode-stdio-1.0+ main-is: hole.hs+ hs-source-dirs: test+ other-modules: Test, Test.ListableExpr+ build-depends: base >= 4 && < 5, express, leancheck >= 0.8+ default-language: Haskell2010++test-suite match+ type: exitcode-stdio-1.0+ main-is: match.hs+ hs-source-dirs: test+ other-modules: Test, Test.ListableExpr+ build-depends: base >= 4 && < 5, express, leancheck >= 0.8+ default-language: Haskell2010++test-suite map+ type: exitcode-stdio-1.0+ main-is: map.hs+ hs-source-dirs: test+ other-modules: Test, Test.ListableExpr+ build-depends: base >= 4 && < 5, express, leancheck >= 0.8+ default-language: Haskell2010++test-suite fixtures+ type: exitcode-stdio-1.0+ main-is: fixtures.hs+ hs-source-dirs: test+ other-modules: Test, Test.ListableExpr+ build-depends: base >= 4 && < 5, express, leancheck >= 0.8+ default-language: Haskell2010++test-suite instances+ type: exitcode-stdio-1.0+ main-is: instances.hs+ hs-source-dirs: test+ other-modules: Test, Test.ListableExpr+ build-depends: base >= 4 && < 5, express, leancheck >= 0.8+ default-language: Haskell2010++test-suite express-instances+ type: exitcode-stdio-1.0+ main-is: express.hs+ hs-source-dirs: test+ other-modules: Test, Test.ListableExpr+ build-depends: base >= 4 && < 5, express, leancheck >= 0.8+ default-language: Haskell2010++test-suite express-derive+ type: exitcode-stdio-1.0+ main-is: express-derive.hs+ hs-source-dirs: test+ other-modules: Test, Test.ListableExpr+ build-depends: base >= 4 && < 5, express, leancheck >= 0.8+ default-language: Haskell2010++test-suite ord+ type: exitcode-stdio-1.0+ main-is: ord.hs+ hs-source-dirs: test+ other-modules: Test, Test.ListableExpr+ build-depends: base >= 4 && < 5, express, leancheck >= 0.8+ default-language: Haskell2010++test-suite listable+ type: exitcode-stdio-1.0+ main-is: listable.hs+ hs-source-dirs: test+ other-modules: Test, Test.ListableExpr+ build-depends: base >= 4 && < 5, express, leancheck >= 0.8+ default-language: Haskell2010++test-suite name+ type: exitcode-stdio-1.0+ main-is: name.hs+ hs-source-dirs: test+ other-modules: Test, Test.ListableExpr+ build-depends: base >= 4 && < 5, express, leancheck >= 0.8+ default-language: Haskell2010++test-suite name-derive+ type: exitcode-stdio-1.0+ main-is: name-derive.hs+ hs-source-dirs: test+ other-modules: Test, Test.ListableExpr+ build-depends: base >= 4 && < 5, express, leancheck >= 0.8+ default-language: Haskell2010++test-suite fold+ type: exitcode-stdio-1.0+ main-is: fold.hs+ hs-source-dirs: test+ other-modules: Test, Test.ListableExpr+ build-depends: base >= 4 && < 5, express, leancheck >= 0.8+ default-language: Haskell2010++test-suite show+ type: exitcode-stdio-1.0+ main-is: show.hs+ hs-source-dirs: test+ other-modules: Test, Test.ListableExpr+ build-depends: base >= 4 && < 5, express, leancheck >= 0.8+ default-language: Haskell2010++test-suite utils+ type: exitcode-stdio-1.0+ main-is: utils.hs+ hs-source-dirs: test+ other-modules: Test, Test.ListableExpr+ build-depends: base >= 4 && < 5, express, leancheck >= 0.8+ default-language: Haskell2010++benchmark compare+ type: exitcode-stdio-1.0+ main-is: compare.hs+ hs-source-dirs: bench, test+ other-modules: Test, Test.ListableExpr+ build-depends: base >= 4 && < 5, express, leancheck >= 0.8+ default-language: Haskell2010++benchmark pairs+ type: exitcode-stdio-1.0+ main-is: pairs.hs+ hs-source-dirs: bench, test+ other-modules: Test, Test.ListableExpr+ build-depends: base >= 4 && < 5, express, leancheck >= 0.8+ default-language: Haskell2010++benchmark tiers+ type: exitcode-stdio-1.0+ main-is: tiers.hs+ hs-source-dirs: bench, test+ other-modules: Test, Test.ListableExpr+ build-depends: base >= 4 && < 5, express, leancheck >= 0.8+ default-language: Haskell2010++benchmark u-extrapolate+ type: exitcode-stdio-1.0+ main-is: u-extrapolate.hs+ hs-source-dirs: eg+ build-depends: base >= 4 && < 5, express, leancheck >= 0.8+ default-language: Haskell2010++benchmark u-speculate+ type: exitcode-stdio-1.0+ main-is: u-speculate.hs+ hs-source-dirs: eg+ build-depends: base >= 4 && < 5, express, leancheck >= 0.8+ default-language: Haskell2010
+ mk/All.hs view
@@ -0,0 +1,8 @@+module All+ ( module Data.Express+ , module Data.Express.Fixtures+ )+where++import Data.Express+import Data.Express.Fixtures
+ mk/Toplibs.hs view
@@ -0,0 +1,5 @@+-- Using ghc --make in this module triggers compilation of every library.+module Toplibs () where++import Data.Express ()+import Test ()
+ mk/depend.mk view
@@ -0,0 +1,814 @@+bench/compare.o: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/TH.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express.hs \+ src/Data/Express/Name.hs \+ src/Data/Express/Name/Derive.hs \+ src/Data/Express/Match.hs \+ src/Data/Express/Map.hs \+ src/Data/Express/Instances.hs \+ src/Data/Express/Hole.hs \+ src/Data/Express/Fold.hs \+ src/Data/Express/Fixtures.hs \+ src/Data/Express/Express.hs \+ src/Data/Express/Express/Derive.hs \+ src/Data/Express/Core.hs \+ src/Data/Express/Canon.hs \+ src/Data/Express/Basic.hs \+ bench/compare.hs+bench/compare: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ bench/compare.hs \+ mk/toplibs+bench/pairs.o: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/TH.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express.hs \+ src/Data/Express/Name.hs \+ src/Data/Express/Name/Derive.hs \+ src/Data/Express/Match.hs \+ src/Data/Express/Map.hs \+ src/Data/Express/Instances.hs \+ src/Data/Express/Hole.hs \+ src/Data/Express/Fold.hs \+ src/Data/Express/Fixtures.hs \+ src/Data/Express/Express.hs \+ src/Data/Express/Express/Derive.hs \+ src/Data/Express/Core.hs \+ src/Data/Express/Canon.hs \+ src/Data/Express/Basic.hs \+ bench/pairs.hs+bench/pairs: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ bench/pairs.hs \+ mk/toplibs+bench/tiers.o: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/TH.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express.hs \+ src/Data/Express/Name.hs \+ src/Data/Express/Name/Derive.hs \+ src/Data/Express/Match.hs \+ src/Data/Express/Map.hs \+ src/Data/Express/Instances.hs \+ src/Data/Express/Hole.hs \+ src/Data/Express/Fold.hs \+ src/Data/Express/Fixtures.hs \+ src/Data/Express/Express.hs \+ src/Data/Express/Express/Derive.hs \+ src/Data/Express/Core.hs \+ src/Data/Express/Canon.hs \+ src/Data/Express/Basic.hs \+ bench/tiers.hs+bench/tiers: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ bench/tiers.hs \+ mk/toplibs+eg/u-extrapolate: \+ eg/u-extrapolate.hs \+ mk/toplibs+eg/u-extrapolate.o: \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/TH.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express.hs \+ src/Data/Express/Name.hs \+ src/Data/Express/Name/Derive.hs \+ src/Data/Express/Match.hs \+ src/Data/Express/Map.hs \+ src/Data/Express/Instances.hs \+ src/Data/Express/Hole.hs \+ src/Data/Express/Fold.hs \+ src/Data/Express/Express.hs \+ src/Data/Express/Express/Derive.hs \+ src/Data/Express/Core.hs \+ src/Data/Express/Canon.hs \+ src/Data/Express/Basic.hs \+ eg/u-extrapolate.hs+eg/u-speculate: \+ eg/u-speculate.hs \+ mk/toplibs+eg/u-speculate.o: \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/TH.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express.hs \+ src/Data/Express/Name.hs \+ src/Data/Express/Name/Derive.hs \+ src/Data/Express/Match.hs \+ src/Data/Express/Map.hs \+ src/Data/Express/Instances.hs \+ src/Data/Express/Hole.hs \+ src/Data/Express/Fold.hs \+ src/Data/Express/Express.hs \+ src/Data/Express/Express/Derive.hs \+ src/Data/Express/Core.hs \+ src/Data/Express/Canon.hs \+ src/Data/Express/Basic.hs \+ eg/u-speculate.hs+mk/All.o: \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/TH.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express.hs \+ src/Data/Express/Name.hs \+ src/Data/Express/Name/Derive.hs \+ src/Data/Express/Match.hs \+ src/Data/Express/Map.hs \+ src/Data/Express/Instances.hs \+ src/Data/Express/Hole.hs \+ src/Data/Express/Fold.hs \+ src/Data/Express/Fixtures.hs \+ src/Data/Express/Express.hs \+ src/Data/Express/Express/Derive.hs \+ src/Data/Express/Core.hs \+ src/Data/Express/Canon.hs \+ src/Data/Express/Basic.hs \+ mk/All.hs+mk/Toplibs.o: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/TH.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express.hs \+ src/Data/Express/Name.hs \+ src/Data/Express/Name/Derive.hs \+ src/Data/Express/Match.hs \+ src/Data/Express/Map.hs \+ src/Data/Express/Instances.hs \+ src/Data/Express/Hole.hs \+ src/Data/Express/Fold.hs \+ src/Data/Express/Fixtures.hs \+ src/Data/Express/Express.hs \+ src/Data/Express/Express/Derive.hs \+ src/Data/Express/Core.hs \+ src/Data/Express/Canon.hs \+ src/Data/Express/Basic.hs \+ mk/Toplibs.hs+Setup.o: \+ Setup.hs+Setup: \+ Setup.hs \+ mk/toplibs+src/Data/Express/Basic.o: \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express/Map.hs \+ src/Data/Express/Hole.hs \+ src/Data/Express/Fold.hs \+ src/Data/Express/Core.hs \+ src/Data/Express/Basic.hs+src/Data/Express/Canon: \+ mk/toplibs+src/Data/Express/Canon.o: \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express/Name.hs \+ src/Data/Express/Map.hs \+ src/Data/Express/Instances.hs \+ src/Data/Express/Hole.hs \+ src/Data/Express/Fold.hs \+ src/Data/Express/Express.hs \+ src/Data/Express/Core.hs \+ src/Data/Express/Canon.hs \+ src/Data/Express/Basic.hs+src/Data/Express/Core.o: \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express/Core.hs+src/Data/Express/Express/Derive.o: \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/TH.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express/Express.hs \+ src/Data/Express/Express/Derive.hs \+ src/Data/Express/Core.hs+src/Data/Express/Express.o: \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express/Express.hs \+ src/Data/Express/Core.hs+src/Data/Express/Fixtures: \+ mk/toplibs+src/Data/Express/Fixtures.o: \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/TH.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express.hs \+ src/Data/Express/Name.hs \+ src/Data/Express/Name/Derive.hs \+ src/Data/Express/Match.hs \+ src/Data/Express/Map.hs \+ src/Data/Express/Instances.hs \+ src/Data/Express/Hole.hs \+ src/Data/Express/Fold.hs \+ src/Data/Express/Fixtures.hs \+ src/Data/Express/Express.hs \+ src/Data/Express/Express/Derive.hs \+ src/Data/Express/Core.hs \+ src/Data/Express/Canon.hs \+ src/Data/Express/Basic.hs+src/Data/Express/Fold.o: \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express/Fold.hs \+ src/Data/Express/Core.hs+src/Data/Express/Hole.o: \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express/Hole.hs \+ src/Data/Express/Core.hs+src/Data/Express/Instances.o: \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express/Name.hs \+ src/Data/Express/Map.hs \+ src/Data/Express/Instances.hs \+ src/Data/Express/Hole.hs \+ src/Data/Express/Fold.hs \+ src/Data/Express/Express.hs \+ src/Data/Express/Core.hs \+ src/Data/Express/Basic.hs+src/Data/Express/Map.o: \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express/Map.hs \+ src/Data/Express/Core.hs+src/Data/Express/Match.o: \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express/Match.hs \+ src/Data/Express/Map.hs \+ src/Data/Express/Hole.hs \+ src/Data/Express/Fold.hs \+ src/Data/Express/Core.hs \+ src/Data/Express/Basic.hs+src/Data/Express/Name/Derive.o: \+ src/Data/Express/Utils/TH.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Name.hs \+ src/Data/Express/Name/Derive.hs+src/Data/Express/Name.o: \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Name.hs+src/Data/Express.o: \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/TH.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express.hs \+ src/Data/Express/Name.hs \+ src/Data/Express/Name/Derive.hs \+ src/Data/Express/Match.hs \+ src/Data/Express/Map.hs \+ src/Data/Express/Instances.hs \+ src/Data/Express/Hole.hs \+ src/Data/Express/Fold.hs \+ src/Data/Express/Express.hs \+ src/Data/Express/Express/Derive.hs \+ src/Data/Express/Core.hs \+ src/Data/Express/Canon.hs \+ src/Data/Express/Basic.hs+src/Data/Express/Utils/List.o: \+ src/Data/Express/Utils/List.hs+src/Data/Express/Utils/String.o: \+ src/Data/Express/Utils/String.hs+src/Data/Express/Utils/TH.o: \+ src/Data/Express/Utils/TH.hs+src/Data/Express/Utils/Typeable.o: \+ src/Data/Express/Utils/Typeable.hs+test/canon.o: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ test/canon.hs \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/TH.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express.hs \+ src/Data/Express/Name.hs \+ src/Data/Express/Name/Derive.hs \+ src/Data/Express/Match.hs \+ src/Data/Express/Map.hs \+ src/Data/Express/Instances.hs \+ src/Data/Express/Hole.hs \+ src/Data/Express/Fold.hs \+ src/Data/Express/Fixtures.hs \+ src/Data/Express/Express.hs \+ src/Data/Express/Express/Derive.hs \+ src/Data/Express/Core.hs \+ src/Data/Express/Canon.hs \+ src/Data/Express/Basic.hs+test/canon: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ test/canon.hs \+ mk/toplibs+test/core.o: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ test/core.hs \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/TH.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express.hs \+ src/Data/Express/Name.hs \+ src/Data/Express/Name/Derive.hs \+ src/Data/Express/Match.hs \+ src/Data/Express/Map.hs \+ src/Data/Express/Instances.hs \+ src/Data/Express/Hole.hs \+ src/Data/Express/Fold.hs \+ src/Data/Express/Fixtures.hs \+ src/Data/Express/Express.hs \+ src/Data/Express/Express/Derive.hs \+ src/Data/Express/Core.hs \+ src/Data/Express/Canon.hs \+ src/Data/Express/Basic.hs+test/core: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ test/core.hs \+ mk/toplibs+test/express-derive.o: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ test/express-derive.hs \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/TH.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express.hs \+ src/Data/Express/Name.hs \+ src/Data/Express/Name/Derive.hs \+ src/Data/Express/Match.hs \+ src/Data/Express/Map.hs \+ src/Data/Express/Instances.hs \+ src/Data/Express/Hole.hs \+ src/Data/Express/Fold.hs \+ src/Data/Express/Fixtures.hs \+ src/Data/Express/Express.hs \+ src/Data/Express/Express/Derive.hs \+ src/Data/Express/Core.hs \+ src/Data/Express/Canon.hs \+ src/Data/Express/Basic.hs+test/express-derive: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ test/express-derive.hs \+ mk/toplibs+test/express.o: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ test/express.hs \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/TH.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express.hs \+ src/Data/Express/Name.hs \+ src/Data/Express/Name/Derive.hs \+ src/Data/Express/Match.hs \+ src/Data/Express/Map.hs \+ src/Data/Express/Instances.hs \+ src/Data/Express/Hole.hs \+ src/Data/Express/Fold.hs \+ src/Data/Express/Fixtures.hs \+ src/Data/Express/Express.hs \+ src/Data/Express/Express/Derive.hs \+ src/Data/Express/Core.hs \+ src/Data/Express/Canon.hs \+ src/Data/Express/Basic.hs+test/express: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ test/express.hs \+ mk/toplibs+test/fixtures.o: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ test/fixtures.hs \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/TH.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express.hs \+ src/Data/Express/Name.hs \+ src/Data/Express/Name/Derive.hs \+ src/Data/Express/Match.hs \+ src/Data/Express/Map.hs \+ src/Data/Express/Instances.hs \+ src/Data/Express/Hole.hs \+ src/Data/Express/Fold.hs \+ src/Data/Express/Fixtures.hs \+ src/Data/Express/Express.hs \+ src/Data/Express/Express/Derive.hs \+ src/Data/Express/Core.hs \+ src/Data/Express/Canon.hs \+ src/Data/Express/Basic.hs+test/fixtures: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ test/fixtures.hs \+ mk/toplibs+test/fold.o: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ test/fold.hs \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/TH.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express.hs \+ src/Data/Express/Name.hs \+ src/Data/Express/Name/Derive.hs \+ src/Data/Express/Match.hs \+ src/Data/Express/Map.hs \+ src/Data/Express/Instances.hs \+ src/Data/Express/Hole.hs \+ src/Data/Express/Fold.hs \+ src/Data/Express/Fixtures.hs \+ src/Data/Express/Express.hs \+ src/Data/Express/Express/Derive.hs \+ src/Data/Express/Core.hs \+ src/Data/Express/Canon.hs \+ src/Data/Express/Basic.hs+test/fold: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ test/fold.hs \+ mk/toplibs+test/hole.o: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ test/hole.hs \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/TH.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express.hs \+ src/Data/Express/Name.hs \+ src/Data/Express/Name/Derive.hs \+ src/Data/Express/Match.hs \+ src/Data/Express/Map.hs \+ src/Data/Express/Instances.hs \+ src/Data/Express/Hole.hs \+ src/Data/Express/Fold.hs \+ src/Data/Express/Fixtures.hs \+ src/Data/Express/Express.hs \+ src/Data/Express/Express/Derive.hs \+ src/Data/Express/Core.hs \+ src/Data/Express/Canon.hs \+ src/Data/Express/Basic.hs+test/hole: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ test/hole.hs \+ mk/toplibs+test/instances.o: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ test/instances.hs \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/TH.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express.hs \+ src/Data/Express/Name.hs \+ src/Data/Express/Name/Derive.hs \+ src/Data/Express/Match.hs \+ src/Data/Express/Map.hs \+ src/Data/Express/Instances.hs \+ src/Data/Express/Hole.hs \+ src/Data/Express/Fold.hs \+ src/Data/Express/Fixtures.hs \+ src/Data/Express/Express.hs \+ src/Data/Express/Express/Derive.hs \+ src/Data/Express/Core.hs \+ src/Data/Express/Canon.hs \+ src/Data/Express/Basic.hs+test/instances: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ test/instances.hs \+ mk/toplibs+test/listable.o: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ test/listable.hs \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/TH.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express.hs \+ src/Data/Express/Name.hs \+ src/Data/Express/Name/Derive.hs \+ src/Data/Express/Match.hs \+ src/Data/Express/Map.hs \+ src/Data/Express/Instances.hs \+ src/Data/Express/Hole.hs \+ src/Data/Express/Fold.hs \+ src/Data/Express/Fixtures.hs \+ src/Data/Express/Express.hs \+ src/Data/Express/Express/Derive.hs \+ src/Data/Express/Core.hs \+ src/Data/Express/Canon.hs \+ src/Data/Express/Basic.hs+test/listable: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ test/listable.hs \+ mk/toplibs+test/main.o: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ test/main.hs \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/TH.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express.hs \+ src/Data/Express/Name.hs \+ src/Data/Express/Name/Derive.hs \+ src/Data/Express/Match.hs \+ src/Data/Express/Map.hs \+ src/Data/Express/Instances.hs \+ src/Data/Express/Hole.hs \+ src/Data/Express/Fold.hs \+ src/Data/Express/Fixtures.hs \+ src/Data/Express/Express.hs \+ src/Data/Express/Express/Derive.hs \+ src/Data/Express/Core.hs \+ src/Data/Express/Canon.hs \+ src/Data/Express/Basic.hs+test/main: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ test/main.hs \+ mk/toplibs+test/map.o: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ test/map.hs \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/TH.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express.hs \+ src/Data/Express/Name.hs \+ src/Data/Express/Name/Derive.hs \+ src/Data/Express/Match.hs \+ src/Data/Express/Map.hs \+ src/Data/Express/Instances.hs \+ src/Data/Express/Hole.hs \+ src/Data/Express/Fold.hs \+ src/Data/Express/Fixtures.hs \+ src/Data/Express/Express.hs \+ src/Data/Express/Express/Derive.hs \+ src/Data/Express/Core.hs \+ src/Data/Express/Canon.hs \+ src/Data/Express/Basic.hs+test/map: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ test/map.hs \+ mk/toplibs+test/match.o: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ test/match.hs \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/TH.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express.hs \+ src/Data/Express/Name.hs \+ src/Data/Express/Name/Derive.hs \+ src/Data/Express/Match.hs \+ src/Data/Express/Map.hs \+ src/Data/Express/Instances.hs \+ src/Data/Express/Hole.hs \+ src/Data/Express/Fold.hs \+ src/Data/Express/Fixtures.hs \+ src/Data/Express/Express.hs \+ src/Data/Express/Express/Derive.hs \+ src/Data/Express/Core.hs \+ src/Data/Express/Canon.hs \+ src/Data/Express/Basic.hs+test/match: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ test/match.hs \+ mk/toplibs+test/name-derive.o: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ test/name-derive.hs \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/TH.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express.hs \+ src/Data/Express/Name.hs \+ src/Data/Express/Name/Derive.hs \+ src/Data/Express/Match.hs \+ src/Data/Express/Map.hs \+ src/Data/Express/Instances.hs \+ src/Data/Express/Hole.hs \+ src/Data/Express/Fold.hs \+ src/Data/Express/Fixtures.hs \+ src/Data/Express/Express.hs \+ src/Data/Express/Express/Derive.hs \+ src/Data/Express/Core.hs \+ src/Data/Express/Canon.hs \+ src/Data/Express/Basic.hs+test/name-derive: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ test/name-derive.hs \+ mk/toplibs+test/name.o: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ test/name.hs \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/TH.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express.hs \+ src/Data/Express/Name.hs \+ src/Data/Express/Name/Derive.hs \+ src/Data/Express/Match.hs \+ src/Data/Express/Map.hs \+ src/Data/Express/Instances.hs \+ src/Data/Express/Hole.hs \+ src/Data/Express/Fold.hs \+ src/Data/Express/Fixtures.hs \+ src/Data/Express/Express.hs \+ src/Data/Express/Express/Derive.hs \+ src/Data/Express/Core.hs \+ src/Data/Express/Canon.hs \+ src/Data/Express/Basic.hs+test/name: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ test/name.hs \+ mk/toplibs+test/ord.o: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ test/ord.hs \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/TH.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express.hs \+ src/Data/Express/Name.hs \+ src/Data/Express/Name/Derive.hs \+ src/Data/Express/Match.hs \+ src/Data/Express/Map.hs \+ src/Data/Express/Instances.hs \+ src/Data/Express/Hole.hs \+ src/Data/Express/Fold.hs \+ src/Data/Express/Fixtures.hs \+ src/Data/Express/Express.hs \+ src/Data/Express/Express/Derive.hs \+ src/Data/Express/Core.hs \+ src/Data/Express/Canon.hs \+ src/Data/Express/Basic.hs+test/ord: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ test/ord.hs \+ mk/toplibs+test/show.o: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ test/show.hs \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/TH.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express.hs \+ src/Data/Express/Name.hs \+ src/Data/Express/Name/Derive.hs \+ src/Data/Express/Match.hs \+ src/Data/Express/Map.hs \+ src/Data/Express/Instances.hs \+ src/Data/Express/Hole.hs \+ src/Data/Express/Fold.hs \+ src/Data/Express/Fixtures.hs \+ src/Data/Express/Express.hs \+ src/Data/Express/Express/Derive.hs \+ src/Data/Express/Core.hs \+ src/Data/Express/Canon.hs \+ src/Data/Express/Basic.hs+test/show: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ test/show.hs \+ mk/toplibs+test/Test/ListableExpr.o: \+ test/Test/ListableExpr.hs \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/TH.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express.hs \+ src/Data/Express/Name.hs \+ src/Data/Express/Name/Derive.hs \+ src/Data/Express/Match.hs \+ src/Data/Express/Map.hs \+ src/Data/Express/Instances.hs \+ src/Data/Express/Hole.hs \+ src/Data/Express/Fold.hs \+ src/Data/Express/Fixtures.hs \+ src/Data/Express/Express.hs \+ src/Data/Express/Express/Derive.hs \+ src/Data/Express/Core.hs \+ src/Data/Express/Canon.hs \+ src/Data/Express/Basic.hs+test/Test.o: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/TH.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express.hs \+ src/Data/Express/Name.hs \+ src/Data/Express/Name/Derive.hs \+ src/Data/Express/Match.hs \+ src/Data/Express/Map.hs \+ src/Data/Express/Instances.hs \+ src/Data/Express/Hole.hs \+ src/Data/Express/Fold.hs \+ src/Data/Express/Fixtures.hs \+ src/Data/Express/Express.hs \+ src/Data/Express/Express/Derive.hs \+ src/Data/Express/Core.hs \+ src/Data/Express/Canon.hs \+ src/Data/Express/Basic.hs+test/Test: \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ mk/toplibs+test/utils.o: \+ test/utils.hs \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ src/Data/Express/Utils/Typeable.hs \+ src/Data/Express/Utils/TH.hs \+ src/Data/Express/Utils/String.hs \+ src/Data/Express/Utils/List.hs \+ src/Data/Express.hs \+ src/Data/Express/Name.hs \+ src/Data/Express/Name/Derive.hs \+ src/Data/Express/Match.hs \+ src/Data/Express/Map.hs \+ src/Data/Express/Instances.hs \+ src/Data/Express/Hole.hs \+ src/Data/Express/Fold.hs \+ src/Data/Express/Fixtures.hs \+ src/Data/Express/Express.hs \+ src/Data/Express/Express/Derive.hs \+ src/Data/Express/Core.hs \+ src/Data/Express/Canon.hs \+ src/Data/Express/Basic.hs+test/utils: \+ test/utils.hs \+ test/Test.hs \+ test/Test/ListableExpr.hs \+ mk/toplibs
+ mk/ghcdeps view
@@ -0,0 +1,49 @@+#!/bin/bash+#+# ghcdeps: generate Haskell make dependencies for compiling with GHC.+#+# Copyright (c) 2015-2019 Rudy Matela.+# Distributed under the 3-Clause BSD licence.+#+# From a list of files provided on standard input,+# generate flat make dependencies.+#+# Transitive relations are repeated.+#+# Usage:+# $ ghcdeps -isomedir:someother <<LIST+# program.hs+# Library.hs+# Path/To/Library.hs+# LIST+# program: ...+# Library.o: ...+# Path/To/Library.o: ...+#+# Or:+# $ find -name \*.hs -o -name \*.lhs | ghcdeps [GHCFLAGS]+# ...+#+# Note that when using find, you have to remember to exclude unecessary files,+# e.g.: dist, Setup.hs+#+# Yes, this is hacky. But hey, it works.+while read fn+do+ ghc "$@" -dep-suffix=. -dep-makefile=tmp.mk -M "$fn" ||+ exit 1+ deps="`cat tmp.mk |+ grep "hs$" |+ sort |+ sed -e "s/.*: //" |+ tac |+ tr '\n' ' ' |+ sed -e "s/ $//"`"+ obj=`echo $fn | sed -e 's,^\./,,;s/\.hs$/.o/'`+ bin=`echo $fn | sed -e 's,^\./,,;s/\.hs$//'`+ echo "$obj: $deps"+ grep -q "main" "$fn" && echo "$bin: `echo $deps | sed -e 's|[^ ]*src[^ ]*||g'` mk/toplibs"+ rm -f tmp.mk+done |+sort |+sed -e 's, *, \\\n ,g'
+ mk/haddock-i view
@@ -0,0 +1,36 @@+#!/bin/bash+#+# haddock-i: list haddock's -i parameters.+#+# Copyright (c) 2015-2019 Rudy Matela.+# Distributed under the 3-Clause BSD licence.+#+# $ haddock-i <package1> <package2> ... <packageN>+#+# will print -i parameters necessary for haddock to link to Haddock+# documentation installed on your system, so you can:+#+# $ haddock-i base template-haskell | xargs haddock <files>+err() {+ echo "$@" > /dev/stderr+}++errxit() {+ err "$@"+ exit 1+}++iface-for() {+ ghc-pkg field $1 haddock-interfaces | sort -rV | head -1 | sed "s/.*: //"+}++html-for() {+ ghc-pkg field $1 haddock-html | sort -rV | head -1 | sed "s/.*: //"+}++for pkg in "$@"+do+ iface=$(iface-for $pkg)+ html=$(html-for $pkg)+ [ -d "$html" -a -f "$iface" ] && echo "-i$html,$iface" || err "haddock-i: warning: could not find interface file for $pkg"+done
+ mk/haskell.mk view
@@ -0,0 +1,134 @@+# Implicit rules for compiling Haskell code.+#+# Copyright (c) 2015-2019 Rudy Matela.+# Distributed under the 3-Clause BSD licence.+#+# You can optionally configure the "Configuration variables" below in your main+# makefile, e.g.:+#+# GHCIMPORTDIRS = path/to/dir:path/to/another/dir+# GHCFLAGS = -O2 -dynamic+# GHC = ghc-7.6+# include haskell.mk++++# Configuration variables++# GHC Parameters+GHCIMPORTDIRS ?=+GHCFLAGS ?=+GHC ?= ghc+GHCCMD = $(GHC) -i$(GHCIMPORTDIRS) $(GHCFLAGS)+HADDOCK ?= haddock++# Hugs Parameters+HUGSIMPORTDIRS ?= "/usr/lib/hugs/packages/*"+HUGSFLAGS ?=+CPPHS_HUGS ?= cpphs-hugs --noline -D__HUGS__+HUGS ?= hugs+RUNHUGS ?= runhugs+HUGSCMD = $(HUGS) -F"$(CPPHS_HUGS)" -P$(HUGSIMPORTDIRS) $(HUGSFLAGS)+RUNHUGSCMD = $(RUNHUGS) -F"$(CPPHS_HUGS)" -P$(HUGSIMPORTDIRS) $(HUGSFLAGS)+++# Makefile where to keep the dependencies+DEPMK ?= mk/depend.mk++# LIB_HSS: all library Haskell files+# ALL_HSS: all Haskell files+# You can override ALL/LIB_HSS in your main Makefile+LIST_LIB_HSS ?= find src -name "*.hs"+LIST_ALL_HSS ?= find \( -path "./dist" -o -path "./.stack-work" \) -prune \+ -o -name "*.*hs" -print+LIB_HSS ?= $(shell $(LIST_LIB_HSS))+ALL_HSS ?= $(shell $(LIST_ALL_HSS))++LIB_DEPS ?= base+ALL_DEPS ?= $(LIB_DEPS)++PKGNAME = $(shell cat *.cabal | grep "^name:" | sed -e "s/name: *//")+HADDOCK_VERSION = $(shell $(HADDOCK) --version | grep version | sed -e 's/.*version //;s/,.*//')+HADDOCK_MAJOR = $(shell echo $(HADDOCK_VERSION) | sed -e 's/\..*//')+HADDOCK_MINOR = $(shell echo $(HADDOCK_VERSION) | sed -e 's/[0-9]*\.\([0-9]*\).[0-9]*/\1/')+HADDOCK_PKG_NAME = $(shell [ $(HADDOCK_MAJOR) -gt 2 ] \+ || [ $(HADDOCK_MAJOR) -eq 2 -a $(HADDOCK_MINOR) -ge 20 ] \+ && echo "--package-name=$(PKGNAME)")+HADDOCK_HLNK_SRC = $(shell [ $(HADDOCK_MAJOR) -gt 2 ] \+ || [ $(HADDOCK_MAJOR) -eq 2 -a $(HADDOCK_MINOR) -ge 17 ] \+ && echo "--hyperlinked-source")+++# Implicit rules+%.hi %.o: %.hs+ $(GHCCMD) $< && touch $@++%: %.hs+ $(GHCCMD) $< && touch $@++.PHONY: %.ghci+%.ghci: %.hs+ $(GHCCMD) -O0 --interactive $<++.PHONY: %.hugs+%.hugs: %.hs+ $(HUGSCMD) $<++.PHONY: %.runhugs+%.runhugs: %.hs+ $(RUNHUGSCMD) $<+++# Cleaning rule (add as a clean dependency)+.PHONY: clean-hi-o+clean-hi-o:+ find $(ALL_HSS) | sed -e 's/hs$$/o/' | xargs rm -f+ find $(ALL_HSS) | sed -e 's/hs$$/hi/' | xargs rm -f+ find $(ALL_HSS) | sed -e 's/hs$$/dyn_o/' | xargs rm -f+ find $(ALL_HSS) | sed -e 's/hs$$/dyn_hi/' | xargs rm -f+++# Update dependency file+.PHONY: depend+depend:+ find $(ALL_HSS) | ./mk/ghcdeps -i$(GHCIMPORTDIRS) $(GHCFLAGS) > $(DEPMK)++# haddock rules+haddock: doc/index.html++clean-haddock:+ rm -f doc/*.{html,css,js,png,gif,json} doc/src/*.{html,css,js} README.html++upload-haddock:+ @echo "use \`cabal upload -d' instead"+ @echo "(but 1st: cabal install --only-dependencies --enable-documentation)"+ @echo "(to just compile docs: cabal haddock --for-hackage)"+ @echo "(on Arch Linux, use: cabal haddock --for-hackage --haddock-options=--optghc=-dynamic)"++doc/index.html: $(LIB_HSS)+ ./mk/haddock-i $(LIB_DEPS) | xargs \+ $(HADDOCK) --html -odoc $(LIB_HSS) \+ --title=$(PKGNAME) \+ $(HADDOCK_PKG_NAME) \+ $(HADDOCK_HLNK_SRC) \+ $(HADDOCKFLAGS)+++# lists all Haskell source files+list-all-hss:+ @find $(ALL_HSS)++# lists library Haskell source files+list-lib-hss:+ @find $(LIB_HSS)++bootstrap-haskell-mk:+ @[ -d "$(DEST)" ] || (echo -e "error: no destination found\nusage: \`make bootstrap-haskell-mk DEST=path/to/prj'"; exit 1)+ mkdir -p mk+ cp mk/{haskell.mk,ghcdeps,haddock-i} $(DEST)/mk+ touch $(DEST)/mk/depend.mk++show-pkgname:+ @echo $(PKGNAME)++include $(DEPMK)
+ src/Data/Express.hs view
@@ -0,0 +1,259 @@+-- |+-- Module : Data.Express+-- Copyright : (c) 2019 Rudy Matela+-- License : 3-Clause BSD (see the file LICENSE)+-- Maintainer : Rudy Matela <rudy@matela.com.br>+--+-- Express is a library for manipulating dynamically typed Haskell expressions.+-- It's like "Data.Dynamic" but with support for encoding applications and+-- variables.+--+-- It provides the 'Expr' type and over a hundred functions for+-- building, evaluating, comparing, folding, canonicalizing and matching+-- 'Expr's.+--+-- /Example:/+-- Like with "Data.Dynamic", we can use Express to create heterogeneous lists:+--+-- > > let xs = [val False, val True, val (1::Int), val (2::Int), val (3::Integer), val "123"]+-- > > :t xs+-- > xs :: [Expr]+-- > > xs+-- > [ False :: Bool+-- > , True :: Bool+-- > , 1 :: Int+-- > , 2 :: Int+-- > , 3 :: Integer+-- > , "123" :: [Char]+-- > ]+--+-- We can then apply 'evaluate' to select values of different types:+--+-- > > import Data.Maybe+-- > > mapMaybe evaluate xs :: [Bool]+-- > [False,True]+-- > > mapMaybe evaluate xs :: [Int]+-- > [1,2]+-- > > mapMaybe evaluate xs :: [Integer]+-- > [3]+-- > > mapMaybe evaluate xs :: [String]+-- > ["123"]+--+-- If define an heterogeneous list of functions encoded as 'Expr's:+--+-- > > let fs = [value "not" not, value "&&" (&&), value "abs" (abs :: Int -> Int)]+-- > > :t fs+-- > fs :: [Expr]+--+-- Using '$$' we can list the type correct applications+-- between the two previously defined lists:+--+-- > > catMaybes [f $$ x | f <- fs, x <- xs]+-- > [ not False :: Bool+-- > , not True :: Bool+-- > , (False &&) :: Bool -> Bool+-- > , (True &&) :: Bool -> Bool+-- > , abs 1 :: Int+-- > , abs 2 :: Int+-- > ]+--+-- Other uses of Express include:+--+-- * generalizing counter-examples of property-based testing+-- in <https://hackage.haskell.org/package/extrapolate Extrapolate>;+-- * conjecturing equations based on the results of testing+-- in <https://hackage.haskell.org/package/speculate Speculate>.+--+-- In this documentation,+-- the complexity of most functions is given in big O notation+-- where /n/ is the size of the expression being manipulated or produced.+-- There may still be a /m/ cost associated with the values being stored in 'Expr's.+{-# LANGUAGE CPP #-}+module Data.Express+ ( + -- -- -- Data.Express.Core exports -- -- --++ -- * The Expr datatype+ Expr (..)++ -- ** Building Exprs+ , value+ , val+ , ($$)+ , var++ -- ** Evaluating Exprs+ , evaluate+ , eval+ , evl+ , typ+ , etyp+ , mtyp+ , toDynamic++ -- ** Boolean properties of Exprs+ , isValue+ , isApp+ , isVar+ , isConst+ , isIllTyped+ , isWellTyped+ , hasVar+ , isGround++ -- ** Comparing Exprs+ , compareComplexity++ -- ** Properties of Exprs+ , arity+ , size+ , depth+ , height++ -- ** Showing Exprs+ , showExpr+ , showPrecExpr+ , showOpExpr++ -- * Subexpressions++ -- ** Listing subexpressions+ , subexprs+ , values+ , vars+ , consts+ , nubSubexprs+ , nubValues+ , nubVars+ , nubConsts++ -- -- -- Data.Express.Map exports -- -- --++ -- ** Mapping subexpressions+ , mapValues+ , mapVars+ , mapConsts+ , mapSubexprs+ , (//-)+ , (//)+ , renameVarsBy+++ -- -- -- Data.Express.Hole exports -- -- --++ -- * Variables and holes++ -- ** Creating variables+ , varAsTypeOf+ , listVars+ , listVarsAsTypeOf++ -- ** Typed holes+ , hole+ , isHole+ , holes+ , nubHoles+ , holeAsTypeOf+++ -- -- -- Data.Express.Fold exports -- -- --++ -- * Juggling Exprs++ -- ** Folding Exprs+ , fold+ , unfold+ , foldPair+ , unfoldPair+ , foldTrio+ , unfoldTrio+ , foldApp+ , unfoldApp++ -- -- -- Data.Express.Canon exports -- -- --++ -- ** Canonicalizing Exprs+ , canonicalize+ , canonicalizeWith+ , canonicalization+ , canonicalizationWith+ , isCanonical+ , isCanonicalWith+ , canonicalVariations+ , fastCanonicalVariations++ -- -- -- Data.Express.Match exports -- -- --++ -- ** Matching Exprs+ , match+ , matchWith+ , isInstanceOf+ , hasInstanceOf+ , isSubexprOf++ -- -- -- Data.Express.Express exports -- -- --++ -- * Typeclasses++ -- ** The Express typeclass+ , Express (..)+ , deriveExpress+ , deriveExpressCascading+ , deriveExpressIfNeeded++ -- -- -- Data.Express.Name exports -- -- --++ -- ** The Name typeclass+ , Name (..)+ , names+ , variableNamesFromTemplate+ , deriveName+ , deriveNameCascading+ , deriveNameIfNeeded++ -- -- -- Data.Express.Instances exports -- -- --++ -- ** Typeclass instances as Exprs+ , reifyEq+ , reifyOrd+ , reifyEqOrd+ , reifyName++ , mkEq+ , mkOrd+ , mkOrdLessEqual+ , mkName+ , mkNameWith++ , isEq+ , isOrd+ , isEqOrd+ , isEqT+ , isOrdT+ , isEqOrdT++ , mkEquation+ , mkComparisonLE+ , mkComparisonLT+ , mkComparison+ , lookupComparison++ , listVarsWith+ , lookupName+ , lookupNames++ , validApps+ , findValidApp++ , preludeNameInstances+ )+where++import Data.Express.Basic+import Data.Express.Canon+import Data.Express.Match+import Data.Express.Name+import Data.Express.Name.Derive+import Data.Express.Express+import Data.Express.Express.Derive+import Data.Express.Instances
+ src/Data/Express/Basic.hs view
@@ -0,0 +1,30 @@+-- |+-- Module : Data.Express.Basic+-- Copyright : (c) 2019 Rudy Matela+-- License : 3-Clause BSD (see the file LICENSE)+-- Maintainer : Rudy Matela <rudy@matela.com.br>+--+-- Defines the 'Expr' type and _basic_ utilities involving it, including:+--+-- * re-export of "Data.Express.Core"+-- * re-export of "Data.Express.Map"+-- * re-export of "Data.Express.Fold"+-- * re-export of "Data.Express.Hole"+--+-- If you're a Express user,+-- you're probably better of importing "Data.Express".+{-# LANGUAGE CPP #-}+module Data.Express.Basic+ (+ -- * Module re-exports+ module Data.Express.Core+ , module Data.Express.Map+ , module Data.Express.Fold+ , module Data.Express.Hole+ )+where++import Data.Express.Core+import Data.Express.Map+import Data.Express.Fold+import Data.Express.Hole
+ src/Data/Express/Canon.hs view
@@ -0,0 +1,234 @@+-- |+-- Module : Data.Express.Canon+-- Copyright : (c) 2019 Rudy Matela+-- License : 3-Clause BSD (see the file LICENSE)+-- Maintainer : Rudy Matela <rudy@matela.com.br>+--+-- Utilities for canonicalizing 'Expr's with variables.+module Data.Express.Canon+ ( canonicalize+ , canonicalizeWith+ , canonicalization+ , canonicalizationWith+ , isCanonical+ , isCanonicalWith+ , canonicalVariations+ , fastCanonicalVariations+ )+where++import Data.Express.Basic+import Data.Express.Name+import Data.Express.Instances+import Data.List ((\\))++-- |+-- Like 'canonicalize' but allows customization+-- of the list of variable names.+-- (cf. 'lookupNames', 'variableNamesFromTemplate')+--+-- > > canonicalizeWith (const ["i","j","k","l",...]) (xx -+- yy)+-- > i + j :: Int+--+-- The argument 'Expr' 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) :: Int+canonicalizeWith :: (Expr -> [String]) -> Expr -> Expr+canonicalizeWith namesFor e = e //- canonicalizationWith namesFor e++-- |+-- Like 'canonicalization' but allows customization+-- of the list of variable names.+-- (cf. 'lookupNames', 'variableNamesFromTemplate')+canonicalizationWith :: (Expr -> [String]) -> Expr -> [(Expr,Expr)]+canonicalizationWith namesFor e = cr (vars e) []+ where+ cr :: [Expr] -> [(Expr,Expr)] -> [(Expr,Expr)]+ cr [] bs = bs+ cr (e:es) bs = cr es+ $ if e `elem` map fst bs+ then bs+ else (e, n `varAsTypeOf` e):bs+ where+ existingNames = [n | (_,Value ('_':n) _) <- bs]+ freshNames = namesFor e \\ existingNames+ n = head freshNames++-- |+-- Like 'isCanonical' but allows specifying+-- the list of variable names.+isCanonicalWith :: (Expr -> [String]) -> Expr -> Bool+isCanonicalWith ti e = canonicalizeWith ti e == e++-- |+-- Canonicalizes an 'Expr' so that variable names appear in order.+-- Variable names are taken from the 'preludeNameInstances'.+--+-- > > canonicalize (xx -+- yy)+-- > x + y :: Int+--+-- > > canonicalize (yy -+- xx)+-- > x + y :: Int+--+-- > > canonicalize (xx -+- xx)+-- > x + x :: Int+--+-- > > canonicalize (yy -+- yy)+-- > x + x :: Int+--+-- Constants 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 :: Int+canonicalize :: Expr -> Expr+canonicalize = canonicalizeWith names'++-- |+-- Return a canonicalization of an 'Expr'+-- that makes variable names appear in order+-- using 'names' as provided by 'preludeNameInstances'.+-- By using '//-' it can 'canonicalize' 'Expr's.+--+-- > > 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) ]+canonicalization :: Expr -> [(Expr,Expr)]+canonicalization = canonicalizationWith names'++-- |+-- Returns whether an 'Expr' is canonical:+-- if applying 'canonicalize' is an identity+-- using 'names' as provided by 'preludeNameInstances'.+isCanonical :: Expr -> Bool+isCanonical = isCanonicalWith names'++-- 'names' lifted over the 'Expr' type for a handful of prelude Name instances.+names' :: Expr -> [String]+names' = lookupNames preludeNameInstances++-- |+-- Returns all canonical variations of an 'Expr'+-- 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 ]+--+-- > > 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:+--+-- > > canonicalVariations $ val (0 :: Int)+-- > [0 :: Int]+--+-- > > canonicalVariations $ ord' bee+-- > [ord 'b' :: Int]+--+-- > > canonicalVariations $ ii -+- jj+-- > [i + j :: Int]+--+-- Behaviour is undefined when applying this function to expressions already+-- containing variables.+canonicalVariations :: Expr -> [Expr]+canonicalVariations = map canonicalize . fastCanonicalVariations++-- |+-- A faster version of 'canonicalVariations' 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 'canonicalize', the following 'Expr'+-- 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 'canonicalize' disambiguates:+--+-- > > map canonicalize . fastCanonicalVariations $ i_ -+- ord' c_+-- > [x + ord c :: Int]+--+-- This function is useful when resulting 'Expr's 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.+fastCanonicalVariations :: Expr -> [Expr]+fastCanonicalVariations e+ | null hs' = [e]+ | otherwise = concatMap fastCanonicalVariations+ . map (fill e) . fillings 0+ $ [h | h <- hs', typ h == typ h']+ where+ hs' = holes e+ h' = head hs'++ names = variableNamesFromTemplate "x"++ fillings :: Int -> [Expr] -> [[Expr]]+ fillings i [] = [[]] -- no holes, single empty filling+ fillings i (h:hs) =+ concat $ map (names !! i `varAsTypeOf` h:) (fillings (i+1) hs) -- new var+ : [ map (n `varAsTypeOf` h:) (fillings i hs) -- no new variable+ | n <- take i names ]+++-- | Fill holes in an expression.+-- Silently skips holes that are not of the right type.+-- Silently discard remaining expressions.+fill :: Expr -> [Expr] -> Expr+fill e = fst . fill' e+ where+ fill' :: Expr -> [Expr] -> (Expr,[Expr])+ fill' (e1 :$ e2) es = let (e1',es') = fill' e1 es+ (e2',es'') = fill' e2 es'+ in (e1' :$ e2', es'')+ fill' eh (e:es) | isHole eh && typ eh == typ e = (e,es)+ fill' e es = (e,es)+-- TODO: copy tests from Speculate+-- TODO: add examples on Haddock+-- TODO: export? consider exporting 'fill' from the Hole module
+ src/Data/Express/Core.hs view
@@ -0,0 +1,1060 @@+-- |+-- Module : Data.Express.Core+-- Copyright : (c) 2019 Rudy Matela+-- License : 3-Clause BSD (see the file LICENSE)+-- Maintainer : Rudy Matela <rudy@matela.com.br>+--+-- This module defines the 'Expr' type and basic utilities involving it.+--+-- This is the core of the Express library.+-- As a user, you are probably better of importing "Data.Express".+-- If you want to understand how the library works,+-- this is the place to start.+--+-- The complexity of most functions are given in big O notation+-- where /n/ is the size of the expression being manipulated or produced.+-- There may still be a /m/ cost associated with the values being stored in 'Expr's.+{-# LANGUAGE DeriveDataTypeable #-} -- for GHC < 7.10+module Data.Express.Core+ (+ -- * The Expr datatype+ Expr (..)++ -- * Smart constructors+ , value+ , val+ , ($$)+ , var++ -- * Evaluating Exprs+ , evaluate+ , eval+ , evl+ , typ+ , etyp+ , mtyp+ , toDynamic++ -- * Boolean properties+ , isValue+ , isApp+ , isVar+ , isConst+ , isIllTyped+ , isWellTyped+ , hasVar+ , isGround++ -- * Comparison+ , compareComplexity++ -- * Properties+ , arity+ , size+ , depth+ , height++ -- * Listing subexpressions+ , subexprs+ , values+ , vars+ , consts+ , nubSubexprs+ , nubValues+ , nubVars+ , nubConsts++ -- * Other utilities+ , unfoldApp+ , showExpr+ , showOpExpr+ , showPrecExpr+ )+where++import Data.Dynamic+import Data.Function (on)+import Data.List (intercalate, sort)+import Data.Maybe (fromMaybe, isNothing, isJust)+import Data.Either (either)+import Data.Monoid ((<>))++import Data.Express.Utils.List+import Data.Express.Utils.String+import Data.Express.Utils.Typeable++-- |+-- Values of type 'Expr' represent objects or applications between objects.+-- Each object is encapsulated together with its type and string representation.+-- Values encoded in 'Expr's are always monomorphic.+--+-- An 'Expr' can be constructed using:+--+-- * 'val', for values that are 'Show' instances;+-- * 'value', for values that are not 'Show' instances, like functions;+-- * ':$', for applications between 'Expr's.+--+-- > > val False+-- > False :: Bool+--+-- > > value "not" not :$ val False+-- > not False :: Bool+--+-- An 'Expr' can be evaluated using 'evaluate', 'eval' or 'evl'.+--+-- > > evl $ val (1 :: Int) :: Int+-- > 1+--+-- > > evaluate $ val (1 :: Int) :: Maybe Bool+-- > Nothing+--+-- > > eval 'a' (val 'b')+-- > 'b'+--+-- 'Show'ing a value of type 'Expr' will return a pretty-printed representation+-- of the expression together with its type.+--+-- > > show (value "not" not :$ val False)+-- > "not False :: Bool"+--+-- 'Expr' is like 'Dynamic' but has support for applications and variables+-- (':$', 'var').+--+-- /The 'var' underscore convention:/+-- Functions that manipulate 'Expr's usually follow the convention+-- where a 'value' whose 'String' representation starts with @'_'@+-- represents a 'var'iable.+data Expr = Value String Dynamic -- ^ a 'value' enconded as 'String' and 'Dynamic'+ | Expr :$ Expr -- ^ function application between expressions+ deriving Typeable -- for GHC < 7.10++-- | /O(1)/.+-- It takes a string representation of a value and a value, returning an+-- 'Expr' with that terminal value.+-- For instances of 'Show', it is preferable to use 'val'.+--+-- > > value "0" (0 :: Integer)+-- > 0 :: Integer+--+-- > > value "'a'" 'a'+-- > 'a' :: Char+--+-- > > value "True" True+-- > True :: Bool+--+-- > > value "id" (id :: Int -> Int)+-- > id :: Int -> Int+--+-- > > value "(+)" ((+) :: Int -> Int -> Int)+-- > (+) :: Int -> Int -> Int+--+-- > > value "sort" (sort :: [Bool] -> [Bool])+-- > sort :: [Bool] -> [Bool]+value :: Typeable a => String -> a -> Expr+value s x = Value s (toDyn x)++-- | /O(1)/.+-- A shorthand for 'value' for values that are 'Show' instances.+--+-- > > val (0 :: Int)+-- > 0 :: Int+--+-- > > val 'a'+-- > 'a' :: Char+--+-- > > val True+-- > True :: Bool+--+-- Example equivalences to 'value':+--+-- > val 0 = value "0" 0+-- > val 'a' = value "'a'" 'a'+-- > val True = value "True" True+val :: (Typeable a, Show a) => a -> Expr+val x = value (show x) x++-- | /O(n)/.+-- Creates an 'Expr' representing a function application.+-- 'Just' an 'Expr' application if the types match, 'Nothing' otherwise.+-- (cf. ':$')+--+-- > > value "id" (id :: () -> ()) $$ val ()+-- > Just (id () :: ())+--+-- > > value "abs" (abs :: Int -> Int) $$ val (1337 :: Int)+-- > Just (abs 1337 :: Int)+--+-- > > value "abs" (abs :: Int -> Int) $$ val 'a'+-- > Nothing+--+-- > > value "abs" (abs :: Int -> Int) $$ val ()+-- > Nothing+($$) :: Expr -> Expr -> Maybe Expr+e1 $$ e2 | isIllTyped e = Nothing+ | otherwise = Just e+ where+ e = e1 :$ e2++-- | /O(1)/.+-- Creates an 'Expr' 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 'value' whose string representation+-- starts with underscore (@'_'@).+var :: Typeable a => String -> a -> Expr+var s a = value ('_':s) (undefined `asTypeOf` a)++-- | /O(n)/.+-- Computes the type of an expression. This raises errors, but this should+-- not happen if expressions are smart-constructed.+--+-- > > 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'+typ :: Expr -> TypeRep+typ = either err id . etyp+ where+ err (t1, t2) = error $ "type mismatch, cannot apply `"+ ++ show t1 ++ "' to `" ++ show t2 ++ "'"++-- | /O(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)+--+-- > > etyp ((absE :$ bee) :$ one)+-- > Left (Int -> Int, Char)+etyp :: Expr -> Either (TypeRep, TypeRep) TypeRep+etyp (Value _ d) = Right $ dynTypeRep d+etyp (e1 :$ e2) = case (etyp e1, etyp e2) of+ (Right t1, Right t2) -> case t1 `funResultTy` t2 of+ Nothing -> Left (t1,t2)+ Just t -> Right t+ (Left e, _) -> Left e+ (_, Left e) -> Left e++-- | /O(n)/.+-- Returns 'Just' the type of an expression+-- or 'Nothing' 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)+-- > Nothing+mtyp :: Expr -> Maybe TypeRep+mtyp = either (const Nothing) Just . etyp++-- | /O(n)/.+-- Returns whether the given 'Expr' is ill typed.+-- (cf. 'isWellTyped')+--+-- > > 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')+-- > True+isIllTyped :: Expr -> Bool+isIllTyped = isNothing . mtyp++-- | /O(n)/.+-- Returns whether the given 'Expr' is well typed.+-- (cf. 'isIllTyped')+--+-- > > isWellTyped (absE :$ val (1 :: Int))+-- > True+--+-- > > isWellTyped (absE :$ val 'b')+-- > False+isWellTyped :: Expr -> Bool+isWellTyped = isJust . mtyp++-- | /O(n)/.+-- 'Just' the value of an expression when possible (correct type),+-- 'Nothing' otherwise.+-- This does not catch errors from 'undefined' 'Dynamic' 'value'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'+--+-- > > evaluate $ negateE :$ one :: Maybe Int+-- > Just (-1)+--+-- > > evaluate $ negateE :$ bee :: Maybe Int+-- > Nothing+evaluate :: Typeable a => Expr -> Maybe a+evaluate e = toDynamic e >>= fromDynamic++-- | /O(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+-- > 0+eval :: Typeable a => a -> Expr -> a+eval x e = fromMaybe x (evaluate e)++-- | /O(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 'eval' or 'evaluate'.+evl :: Typeable a => Expr -> a+evl e = r+ where+ r = eval err e+ err = error $ "evl: cannot evaluate Expr `" ++ show e ++ "' at the " ++ show (typeOf r) ++ " type"++-- | /O(n)/.+-- Evaluates an expression to a terminal 'Dynamic' value when possible.+-- Returns 'Nothing' otherwise.+--+-- > > toDynamic $ val (123 :: Int) :: Maybe Dynamic+-- > Just <<Int>>+--+-- > > toDynamic $ value "abs" (abs :: Int -> Int) :$ val (-1 :: Int)+-- > Just <<Int>>+--+-- > > toDynamic $ value "abs" (abs :: Int -> Int) :$ val 'a'+-- > Nothing+toDynamic :: Expr -> Maybe Dynamic+toDynamic (Value _ x) = Just x+toDynamic (e1 :$ e2) = do v1 <- toDynamic e1+ v2 <- toDynamic e2+ dynApply v1 v2++instance Show Expr where+ showsPrec d e = showParen (d > 10)+ $ showsPrecExpr 0 e+ . showString " :: "+ . showsTypeExpr e+-- TODO: document Show Expr++showsTypeExpr :: Expr -> String -> String+showsTypeExpr e = case etyp e of+ Left (t1,t2) -> showString "ill-typed # "+ . shows t1+ . showString " $ "+ . shows t2+ . showString " #"+ Right t -> shows t++showsPrecExpr :: Int -> Expr -> String -> String+showsPrecExpr d (Value "_" _) = showString "_" -- a hole+showsPrecExpr d (Value ('_':s) _) = showParen (isInfix s) $ showString s -- a variable+showsPrecExpr d (Value s _) | isInfixedPrefix s = showString $ toPrefix s+showsPrecExpr d (Value s _) | isNegativeLiteral s = showParen (d > 0) $ showString s+showsPrecExpr d (Value s _) = showParen sp $ showString s+ where sp = if atomic s then isInfix s else maybe True (d >) $ outernmostPrec s+showsPrecExpr d ((Value ":" _ :$ e1) :$ e2)+ | isConst e1 && mtyp e1 == Just (typeOf (undefined :: Char)) =+ case showsTailExpr e2 "" of+ '\"':cs -> showString ("\"" ++ (init . tail) (showsPrecExpr 0 e1 "") ++ cs)+ cs -> showParen (d > prec ":")+ $ showsOpExpr ":" e1 . showString ":" . showString cs+showsPrecExpr d ((Value ":" _ :$ e1) :$ e2) =+ case showsTailExpr e2 "" of+ "[]" -> showString "[" . showsPrecExpr 0 e1 . showString "]"+ '[':cs -> showString "[" . showsPrecExpr 0 e1 . showString "," . showString cs+ cs -> showParen (d > prec ":")+ $ showsOpExpr ":" e1 . showString ":" . showString cs+showsPrecExpr d ee | isTuple ee = id+ showString "("+ . foldr1 (\s1 s2 -> s1 . showString "," . s2)+ (showsPrecExpr 0 `map` unfoldTuple ee)+ . showString ")"+showsPrecExpr d ((Value f' _ :$ e1) :$ e2)+ | isInfix f = showParen (d > prec f)+ $ showsOpExpr f e1+ . showString " " . showString f . showString " "+ . showsOpExpr f e2+ | otherwise = showParen (d > prec " ")+ $ showString f+ . showString " " . showsOpExpr " " e1+ . showString " " . showsOpExpr " " e2+ where+ f = case f' of "_" -> "_" -- holes are shown as _+ ('_':f) -> f -- on variables we drop the preceding _+ f -> f -- constants as themselves+showsPrecExpr d (Value f' _ :$ e1)+ | isInfix f = showParen True+ $ showsOpExpr f e1 . showString " " . showString f+ where+ f = case f' of "_" -> "_" -- holes are shown as _+ ('_':f) -> f -- on variables we drop the preceding _+ f -> f -- constants as themselves+showsPrecExpr d (e1 :$ e2) = showParen (d > prec " ")+ $ showsPrecExpr (prec " ") e1+ . showString " "+ . showsPrecExpr (prec " " + 1) e2++-- bad smell here, repeated code!+showsTailExpr :: Expr -> String -> String+showsTailExpr ((Value ":" _ :$ e1) :$ e2)+ | isConst e1 && mtyp e1 == Just (typeOf (undefined :: Char)) =+ case showsPrecExpr 0 e2 "" of+ '\"':cs -> showString ("\"" ++ (init . tail) (showsPrecExpr 0 e1 "") ++ cs)+ cs -> showsOpExpr ":" e1 . showString ":" . showsTailExpr e2+showsTailExpr ((Value ":" _ :$ e1) :$ e2) =+ case showsPrecExpr 0 e2 "" of+ "[]" -> showString "[" . showsPrecExpr 0 e1 . showString "]"+ '[':cs -> showString "[" . showsPrecExpr 0 e1 . showString "," . showString cs+ cs -> showsOpExpr ":" e1 . showString ":" . showsTailExpr e2+showsTailExpr e = showsOpExpr ":" e++showsOpExpr :: String -> Expr -> String -> String+showsOpExpr op = showsPrecExpr (prec op + 1)++showOpExpr :: String -> Expr -> String+showOpExpr op = showPrecExpr (prec op + 1)++showPrecExpr :: Int -> Expr -> String+showPrecExpr n e = showsPrecExpr n e ""++-- | /O(n)/.+-- Returns a string representation of an expression.+-- Differently from 'show' (@:: Expr -> String@)+-- 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)+showExpr :: Expr -> String+showExpr = showPrecExpr 0++-- | /O(n)/.+-- Does not evaluate values when comparing, but rather uses their+-- representation as strings and their types.+--+-- This instance works for ill-typed expressions.+instance Eq Expr where+ Value s1 d1 == Value s2 d2 = s1 == s2 && dynTypeRep d1 == dynTypeRep d2+ ef1 :$ ex1 == ef2 :$ ex2 = ef1 == ef2 && ex1 == ex2+ _ == _ = False++instance Ord Expr where+ compare = compareComplexity <> lexicompare+-- TODO: document Ord Expr++-- | /O(n)/.+-- Compares the complexity of two 'Expr's.+-- An expression /e1/ is /strictly simpler/ than another expression /e2/+-- if the first of the following conditions to distingish between them is:+--+-- 1. /e1/ is smaller in size\/length than /e2/,+-- e.g.: @x + y < x + (y + z)@;+--+-- 2. or, /e1/ has more distinct variables than /e2/,+-- e.g.: @x + y < x + x@;+--+-- 3. or, /e1/ has more variable occurrences than /e2/,+-- e.g.: @x + x < 1 + x@;+--+-- 4. or, /e1/ has fewer distinct constants than /e2/,+-- e.g.: @1 + 1 < 0 + 1@.+--+-- They're otherwise considered of equal complexity,+-- e.g.: @x + y@ and @y + z@.+--+-- > > (xx -+- yy) `compareComplexity` (xx -+- (yy -+- zz))+-- > LT+--+-- > > (xx -+- yy) `compareComplexity` (xx -+- xx)+-- > LT+--+-- > > (xx -+- xx) `compareComplexity` (one -+- xx)+-- > LT+--+-- > > (one -+- one) `compareComplexity` (zero -+- one)+-- > LT+--+-- > > (xx -+- yy) `compareComplexity` (yy -+- zz)+-- > EQ+--+-- > > (zero -+- one) `compareComplexity` (one -+- zero)+-- > EQ+compareComplexity :: Expr -> Expr -> Ordering+compareComplexity = (compare `on` length . values)+ <> (flip compare `on` length . nubVars)+ <> (flip compare `on` length . vars)+ <> (compare `on` length . nubConsts)++lexicompareBy :: (Expr -> Expr -> Ordering) -> Expr -> Expr -> Ordering+lexicompareBy compareConstants = cmp+ where+ e1@(Value ('_':s1) _) `cmp` e2@(Value ('_':s2) _) = typ e1 `compareTy` typ e2+ <> s1 `compare` s2+ (f :$ x) `cmp` (g :$ y) = f `cmp` g <> x `cmp` y+ (_ :$ _) `cmp` _ = GT+ _ `cmp` (_ :$ _) = LT+ _ `cmp` Value ('_':_) _ = GT+ Value ('_':_) _ `cmp` _ = LT+ e1@(Value _ _) `cmp` e2@(Value _ _) = e1 `compareConstants` e2+ -- Var < Constants < Apps++lexicompareConstants :: Expr -> Expr -> Ordering+lexicompareConstants = cmp+ where+ e1 `cmp` e2 | typ e1 /= typ e2 = typ e1 `compareTy` typ e2+ Value s1 _ `cmp` Value s2 _ = s1 `compare` s2+ _ `cmp` _ = error "lexicompareConstants can only compare constants"++lexicompare :: Expr -> Expr -> Ordering+lexicompare = lexicompareBy lexicompareConstants++-- | /O(n)/.+-- Unfold a function application 'Expr' 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 ':$' 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]+unfoldApp :: Expr -> [Expr]+unfoldApp e = u e []+ where+ u (ef :$ ex) = u ef . (ex:)+ u ex = (ex:)++-- | /O(n)/.+-- Unfold a tuple 'Expr' into a list of values.+--+-- > > let pair' a b = value "," ((,) :: Bool->Char->(Bool,Char)) :$ a :$ b+--+-- > > pair' (val True) (val 'a')+-- > (True,'a') :: (Bool,Char)+--+-- > > unfoldTuple $ pair' (val True) (val 'a')+-- > [True :: Bool,'a' :: Char]+--+-- > > let trio' a b c = value ",," ((,,) :: Bool->Char->Int->(Bool,Char,Int)) :$ a :$ b :$ c+--+-- > > trio' (val False) (val 'b') (val (9 :: Int))+-- > (False,'b',9) :: (Bool,Char,Int)+--+-- > > unfoldTuple $ trio' (val False) (val 'b') (val (9 :: Int))+-- > [False :: Bool,'b' :: Char,9 :: Int]+--+-- NOTE: this function returns an empty list when the representation of the+-- tupling function is @(,)@, @(,,)@, @(,,,)@ or @(,,,...)@.+-- This is intentional, allowing the 'Show' 'Expr' instance+-- to present @(,) 1 2@ differently than @(1,2)@.+unfoldTuple :: Expr -> [Expr]+unfoldTuple = u . unfoldApp+ where+ u (Value cs _:es) | not (null es) && cs == replicate (length es - 1) ',' = es+ u _ = []++isTuple :: Expr -> Bool+isTuple = not . null . unfoldTuple++-- | /O(n)/.+-- Check if an 'Expr' has a variable. (By convention, any value whose+-- 'String' representation starts with @'_'@.)+--+-- > > hasVar $ value "not" not :$ val True+-- > False+--+-- > > hasVar $ value "&&" (&&) :$ var "p" (undefined :: Bool) :$ val True+-- > True+hasVar :: Expr -> Bool+hasVar (e1 :$ e2) = hasVar e1 || hasVar e2+hasVar e = isVar e++-- | /O(n)/.+-- Returns whether a 'Expr' 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+-- > False+isGround :: Expr -> Bool+isGround = not . hasVar++-- | /O(1)/.+-- Returns whether an 'Expr' is a terminal constant.+-- (cf. 'isGround').+--+-- > > isConst $ var "x" (undefined :: Int)+-- > False+--+-- > > isConst $ val False+-- > True+--+-- > > isConst $ value "not" not :$ val False+-- > False+isConst :: Expr -> Bool+isConst (Value ('_':_) _) = False+isConst (Value _ _) = True+isConst _ = False++-- | /O(1)/.+-- Returns whether an 'Expr' is a terminal variable ('var').+-- (cf. 'hasVar').+--+-- > > isVar $ var "x" (undefined :: Int)+-- > True+--+-- > > isVar $ val False+-- > False+--+-- > > isVar $ value "not" not :$ var "p" (undefined :: Bool)+-- > False+isVar :: Expr -> Bool+isVar (Value ('_':_) _) = True+isVar _ = False++-- | /O(1)/.+-- Returns whether an 'Expr' is a terminal value ('Value').+--+-- > > 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 'Value' constructor.+--+-- /Properties:/+--+-- * @ isValue (Value e) = True @+--+-- * @ isValue (e1 :$ e2) = False @+--+-- * @ isValue = not . isApp @+--+-- * @ isValue e = isVar e || isConst e @+isValue :: Expr -> Bool+isValue (Value _ _) = True+isValue _ = False++-- | /O(1)/.+-- Returns whether an 'Expr' is an application (':$').+--+-- > > 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 ':$' constructor.+--+-- /Properties:/+--+-- * @ isApp (e1 :$ e2) = True @+--+-- * @ isApp (Value e) = False @+--+-- * @ isApp = not . isValue @+--+-- * @ isApp e = not (isVar e) && not (isConst e) @+isApp :: Expr -> Bool+isApp (_ :$ _) = True+isApp _ = False++-- | /O(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. 'nubSubexprs')+--+-- > > 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+-- > ]+subexprs :: Expr -> [Expr]+subexprs e = s e []+ where+ s :: Expr -> [Expr] -> [Expr]+ s e@(e1 :$ e2) = (e:) . s e1 . s e2+ s e = (e:)++-- | /O(n log n)/ for the spine, /O(n^2)/ for full evaluation.+-- Lists all subexpressions of a given expression without repetitions.+-- This includes the expression itself and partial function applications.+-- (cf. 'subexprs')+--+-- > > 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+-- > ]+nubSubexprs :: Expr -> [Expr]+nubSubexprs = s+ where+ s e@(e1 :$ e2) = [e] +++ s e1 +++ s e2+ s e = [e]+-- TODO: After deciding if I'll stick to this implementation or the old one,+-- add note about complexity:+--+-- While this is /O(n log n)/ on average it is /O(n^2)/ in the worst-case.+-- Worst case = f (g (h (i (j (k (l (m (n x))))))))++-- | /O(n)/.+-- Lists all terminal values in an expression in order and with repetitions.+-- (cf. 'nubValues')+--+-- > > 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 ]+values :: Expr -> [Expr]+values e = v e []+ where+ v :: Expr -> [Expr] -> [Expr]+ v (e1 :$ e2) = v e1 . v e2+ v e = (e:)++-- | /O(n log n)/.+-- Lists all terminal values in an expression without repetitions.+-- (cf. 'values')+--+-- > > 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 ]+nubValues :: Expr -> [Expr]+nubValues = v+ where+ v (e1 :$ e2) = v e1 +++ v e2+ v e = [e]++-- | /O(n)/.+-- List terminal constants in an expression in order and with repetitions.+-- (cf. 'nubConsts')+--+-- > > 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 ]+consts :: Expr -> [Expr]+consts = filter isConst . values++-- | /O(n log n)/.+-- List terminal constants in an expression without repetitions.+-- (cf. 'consts')+--+-- > > nubConsts (xx -+- yy)+-- > [ (+) :: Int -> Int -> Int ]+--+-- > > nubConsts (xx -+- (yy -+- zz))+-- > [ (+) :: Int -> Int -> Int ]+--+-- > > nubConsts (pp -&&- true)+-- > [ True :: Bool+-- > , (&&) :: Bool -> Bool -> Bool ]+nubConsts :: Expr -> [Expr]+nubConsts = c+ where+ c (e1 :$ e2) = c e1 +++ c e2+ c e = [e | isConst e]++-- | /O(n)/.+-- Lists all variables in an expression in order and with repetitions.+-- (cf. 'nubVars')+--+-- > > 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]+vars :: Expr -> [Expr]+vars = filter isVar . values++-- | /O(n log n)/.+-- Lists all variables in an expression without repetitions.+-- (cf. 'vars')+--+-- > > nubVars (yy -+- xx)+-- > [ x :: Int+-- > , y :: Int ]+--+-- > > nubVars (xx -+- (yy -+- xx))+-- > [ x :: Int+-- > , y :: Int ]+--+-- > > nubVars (zero -+- (one -*- two))+-- > []+--+-- > > nubVars (pp -&&- true)+-- > [p :: Bool]+nubVars :: Expr -> [Expr]+nubVars = v+ where+ v (e1 :$ e2) = v e1 +++ v e2+ v e = [e | isVar e]++-- | /O(n)/.+-- Return the arity of the given expression,+-- i.e. the number of arguments that its type takes.+--+-- > > arity (val 0)+-- > 0+--+-- > > arity (val False)+-- > 0+--+-- > > arity (value "id" (id :: Int -> Int))+-- > 1+--+-- > > arity (value "const" (const :: Int -> Int -> Int))+-- > 2+--+-- > > arity (one -+- two)+-- > 0+arity :: Expr -> Int+arity = tyArity . typ++-- | /O(n)/.+-- Returns the size of the given expression,+-- i.e. the number of terminal values in it.+--+-- > > size zero+-- > 1+--+-- > > size (one -+- two)+-- > 3+--+-- > > size (abs' one)+-- > 2+size :: Expr -> Int+size = length . values++-- | /O(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. 'height')+--+-- > > depth zero+-- > 1+--+-- > > depth (one -+- two)+-- > 2+--+-- > > depth (abs' one -+- two)+-- > 3+--+-- Flipping arguments of applications in any of the subterms+-- does not affect the result.+depth :: Expr -> Int+depth e@(_:$_) = 1 + maximum (map depth $ unfoldApp e)+depth _ = 1++-- | /O(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. 'depth')+--+-- > > height zero+-- > 1+--+-- > > height (abs' one)+-- > 2+--+-- > > height ((const' one) two)+-- > 3+--+-- > > height ((const' (abs' one)) two)+-- > 4+--+-- > > height ((const' one) (abs' two))+-- > 3+--+-- Flipping arguments of applications in subterms+-- may change the result of the function.+height :: Expr -> Int+height (e1 :$ e2) = 1 + height e1 `max` height e2+height _ = 1
+ src/Data/Express/Express.hs view
@@ -0,0 +1,243 @@+-- |+-- Module : Data.Express.Express+-- Copyright : (c) 2019 Rudy Matela+-- License : 3-Clause BSD (see the file LICENSE)+-- Maintainer : Rudy Matela <rudy@matela.com.br>+--+-- Defines the 'Express' type class.+{-# LANGUAGE CPP #-}+module Data.Express.Express (Express (..)) where++import Data.Express.Core+import Data.Typeable+import Data.Ratio++-- |+-- 'Express' typeclass instances provide an 'expr' function+-- that allows values to be deeply encoded as applications of 'Expr's.+--+-- > expr False = val False+-- > expr (Just True) = value "Just" (Just :: Bool -> Maybe Bool) :$ val True+--+-- The function 'expr' can be contrasted with the function 'val':+--+-- * 'val' always encodes values as atomic 'Value' 'Expr's --+-- shallow encoding.+-- * 'expr' ideally encodes expressions as applications (':$')+-- between 'Value' 'Expr's --+-- deep encoding.+--+-- Depending on the situation, one or the other may be desirable.+--+-- Instances can be automatically derived using the TH function+-- 'Data.Express.Express.Derive.deriveExpress'.+--+-- The 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 'expr' it may be useful to use auxiliary type binding operators:+-- '-:', '->:', '->>:', ....+--+-- For types with atomic values, just declare @ expr = val @+class Typeable a => Express a where+ expr :: a -> Expr++instance Express () where expr = val+instance Express Bool where expr = val+instance Express Int where expr = val+instance Express Integer where expr = val+instance Express Char where expr = val+instance Express Ordering where expr = val++instance Express a => Express (Maybe a) where+ expr mx@Nothing = value "Nothing" (Nothing -: mx)+ expr mx@(Just x) = value "Just" (Just ->: mx) :$ expr x++instance (Express a, Express b) => Express (Either a b) where+ expr lx@(Left x) = value "Left" (Left ->: lx) :$ expr x+ expr ry@(Right y) = value "Right" (Right ->: ry) :$ expr y++instance (Express a, Express b) => Express (a,b) where+ expr (x,y) = value "," ((,) ->>: (x,y))+ :$ expr x :$ expr y++instance (Express a, Express b, Express c) => Express (a,b,c) where+ expr (x,y,z) = value ",," ((,,) ->>>: (x,y,z))+ :$ expr x :$ expr y :$ expr z++instance (Express a, Express b, Express c, Express d) => Express (a,b,c,d) where+ expr (x,y,z,w) = value ",,," ((,,,) ->>>>: (x,y,z,w))+ :$ expr x :$ expr y :$ expr z :$ expr w++instance Express a => Express [a] where+ expr xs@[]+ | typeOf xs == typeOf "" = value "\"\"" ([] -: xs)+ | otherwise = value "[]" ([] -: xs)+ expr xs@(y:ys) = value ":" ((:) ->>: xs) :$ expr y :$ expr ys+++-- instances of further types and arities --++instance (Integral a, Show a, Express a) => Express (Ratio a) where+ expr = val+-- The following would allow zero denominators+-- expr (n % d) = constant "%" ((%) -:> n) :$ expr n :$ expr d+-- TODO: allow zero denominators as it is not our problem+-- but only after refactoring Extrapolate to use Express+-- note that the "Integral a" restriction above is needed on GHC <= 7.10++instance (Express a, Express b, Express c, Express d, Express e)+ => Express (a,b,c,d,e) where+ expr (x,y,z,w,v) = value ",,,," ((,,,,) ->>>>>: (x,y,z,w,v))+ :$ expr x :$ expr y :$ expr z :$ expr w :$ expr v++instance (Express a, Express b, Express c, Express d, Express e, Express f)+ => Express (a,b,c,d,e,f) where+ expr (x,y,z,w,v,u) = value ",,,,," ((,,,,,) ->>>>>>: (x,y,z,w,v,u))+ :$ expr x :$ expr y :$ expr z :$ expr w :$ expr v :$ expr u++instance ( Express a, Express b, Express c, Express d, Express e, Express f+ , Express g )+ => Express (a,b,c,d,e,f,g) where+ expr (x,y,z,w,v,u,t) = value ",,,,,," ((,,,,,,) ->>>>>>>: (x,y,z,w,v,u,t))+ :$ expr x :$ expr y :$ expr z :$ expr w+ :$ expr v :$ expr u :$ expr t++#if __GLASGOW_HASKELL__ < 710+-- No 8-tuples for you:+-- On GHC 7.8, 8-tuples are not Typeable instances. We could add a standalone+-- deriving clause, but that may cause trouble if some other library does the+-- same. User should declare Generalizable 8-tuples manually when using GHC <=+-- 7.8.+#else+instance ( Express a, Express b, Express c, Express d, Express e, Express f+ , Express g, Express h )+ => Express (a,b,c,d,e,f,g,h) where+ expr (x,y,z,w,v,u,t,s) =+ value ",,,,,,," ((,,,,,,,) ->>>>>>>>: (x,y,z,w,v,u,t,s))+ :$ expr x :$ expr y :$ expr z :$ expr w+ :$ expr v :$ expr u :$ expr t :$ expr s++instance ( Express a, Express b, Express c, Express d, Express e, Express f+ , Express g, Express h, Express i )+ => Express (a,b,c,d,e,f,g,h,i) where+ expr (x,y,z,w,v,u,t,s,r) =+ value ",,,,,,,," ((,,,,,,,,) ->>>>>>>>>: (x,y,z,w,v,u,t,s,r))+ :$ expr x :$ expr y :$ expr z :$ expr w+ :$ expr v :$ expr u :$ expr t :$ expr s+ :$ expr r++instance ( Express a, Express b, Express c, Express d, Express e, Express f+ , Express g, Express h, Express i, Express j )+ => Express (a,b,c,d,e,f,g,h,i,j) where+ expr (x,y,z,w,v,u,t,s,r,q) =+ value ",,,,,,,,," ((,,,,,,,,,) ->>>>>>>>>>: (x,y,z,w,v,u,t,s,r,q))+ :$ expr x :$ expr y :$ expr z :$ expr w+ :$ expr v :$ expr u :$ expr t :$ expr s+ :$ expr r :$ expr q++instance ( Express a, Express b, Express c, Express d, Express e, Express f+ , Express g, Express h, Express i, Express j, Express k )+ => Express (a,b,c,d,e,f,g,h,i,j,k) where+ expr (x,y,z,w,v,u,t,s,r,q,p) =+ value ",,,,,,,,,," ((,,,,,,,,,,) ->>>>>>>>>>>: (x,y,z,w,v,u,t,s,r,q,p))+ :$ expr x :$ expr y :$ expr z :$ expr w+ :$ expr v :$ expr u :$ expr t :$ expr s+ :$ expr r :$ expr q :$ expr p++instance ( Express a, Express b, Express c, Express d, Express e, Express f+ , Express g, Express h, Express i, Express j, Express k, Express l )+ => Express (a,b,c,d,e,f,g,h,i,j,k,l) where+ expr (x,y,z,w,v,u,t,s,r,q,p,o) =+ value ",,,,,,,,,,," ((,,,,,,,,,,,) ->>>>>>>>>>>>: (x,y,z,w,v,u,t,s,r,q,p,o))+ :$ expr x :$ expr y :$ expr z :$ expr w+ :$ expr v :$ expr u :$ expr t :$ expr s+ :$ expr r :$ expr q :$ expr p :$ expr o+#endif++-- type binding utilities --++(-:) :: a -> a -> a+(-:) = asTypeOf -- const+infixl 1 -:++(-:>) :: (a -> b) -> a -> (a -> b)+(-:>) = const+infixl 1 -:>++(->:) :: (a -> b) -> b -> (a -> b)+(->:) = const+infixl 1 ->:++(->:>) :: (a -> b -> c) -> b -> (a -> b -> c)+(->:>) = const+infixl 1 ->:>++(->>:) :: (a -> b -> c) -> c -> (a -> b -> c)+(->>:) = const+infixl 1 ->>:++(->>:>) :: (a -> b -> c -> d) -> c -> (a -> b -> c -> d)+(->>:>) = const+infixl 1 ->>:>++(->>>:) :: (a -> b -> c -> d) -> d -> (a -> b -> c -> d)+(->>>:) = const+infixl 1 ->>>:++(->>>:>) :: (a -> b -> c -> d -> e) -> d -> (a -> b -> c -> d -> e)+(->>>:>) = const+infixl 1 ->>>:>++(->>>>:) :: (a -> b -> c -> d -> e) -> e -> (a -> b -> c -> d -> e)+(->>>>:) = const+infixl 1 ->>>>:++(->>>>:>) :: (a -> b -> c -> d -> e -> f) -> e -> (a -> b -> c -> d -> e -> f)+(->>>>:>) = const+infixl 1 ->>>>:>++(->>>>>:) :: (a -> b -> c -> d -> e -> f) -> f -> (a -> b -> c -> d -> e -> f)+(->>>>>:) = const+infixl 1 ->>>>>:++(->>>>>:>) :: (a->b->c->d->e->f->g) -> f -> (a->b->c->d->e->f->g)+(->>>>>:>) = const+infixl 1 ->>>>>:>++(->>>>>>:) :: (a->b->c->d->e->f->g) -> g -> (a->b->c->d->e->f->g)+(->>>>>>:) = const+infixl 1 ->>>>>>:++(->>>>>>>:) :: (a->b->c->d->e->f->g->h) -> h -> (a->b->c->d->e->f->g->h)+(->>>>>>>:) = const+infixl 1 ->>>>>>>:++(->>>>>>>>:) :: (a->b->c->d->e->f->g->h->i) -> i -> (a->b->c->d->e->f->g->h->i)+(->>>>>>>>:) = const+infixl 1 ->>>>>>>>:++(->>>>>>>>>:) :: (a->b->c->d->e->f->g->h->i->j) -> j+ -> (a->b->c->d->e->f->g->h->i->j)+(->>>>>>>>>:) = const+infixl 1 ->>>>>>>>>:++(->>>>>>>>>>:) :: (a->b->c->d->e->f->g->h->i->j->k) -> k+ -> (a->b->c->d->e->f->g->h->i->j->k)+(->>>>>>>>>>:) = const+infixl 1 ->>>>>>>>>>:++(->>>>>>>>>>>:) :: (a->b->c->d->e->f->g->h->i->j->k->l) -> l+ -> (a->b->c->d->e->f->g->h->i->j->k->l)+(->>>>>>>>>>>:) = const+infixl 1 ->>>>>>>>>>>:++(->>>>>>>>>>>>:) :: (a->b->c->d->e->f->g->h->i->j->k->l->m) -> m+ -> (a->b->c->d->e->f->g->h->i->j->k->l->m)+(->>>>>>>>>>>>:) = const+infixl 1 ->>>>>>>>>>>>:
+ src/Data/Express/Express/Derive.hs view
@@ -0,0 +1,70 @@+{-# LANGUAGE TemplateHaskell, CPP #-}+-- |+-- Module : Data.Express.Express.Derive+-- Copyright : (c) 2019 Rudy Matela+-- License : 3-Clause BSD (see the file LICENSE)+-- Maintainer : Rudy Matela <rudy@matela.com.br>+--+-- Allows automatic derivation of 'Express' typeclass instances.+module Data.Express.Express.Derive+ ( deriveExpress+ , deriveExpressCascading+ , deriveExpressIfNeeded+ )+where++import Data.Express.Core+import Data.Express.Express++import Control.Monad+import Data.Char+import Data.List+import Data.Express.Utils.TH++-- | Derives an 'Express' instance for the given type 'Name'.+--+-- This function needs the @TemplateHaskell@ extension.+deriveExpress :: Name -> DecsQ+deriveExpress = deriveWhenNeededOrWarn ''Express reallyDeriveExpress++-- | Same as 'deriveExpress' but does not warn when instance already exists+-- ('deriveExpress' is preferable).+deriveExpressIfNeeded :: Name -> DecsQ+deriveExpressIfNeeded = deriveWhenNeeded ''Express reallyDeriveExpress++-- | Derives a 'Express' instance for a given type 'Name'+-- cascading derivation of type arguments as well.+deriveExpressCascading :: Name -> DecsQ+deriveExpressCascading = deriveWhenNeeded ''Express reallyDeriveExpressCascading++reallyDeriveExpress :: Name -> DecsQ+reallyDeriveExpress t = do+ isEq <- t `isInstanceOf` ''Eq+ isOrd <- t `isInstanceOf` ''Ord+ (nt,vs) <- normalizeType t+#if __GLASGOW_HASKELL__ >= 710+ cxt <- sequence [ [t| $(conT c) $(return v) |]+#else+ -- template-haskell <= 2.9.0.0:+ cxt <- sequence [ classP c [return v]+#endif+ | c <- ''Express:([''Eq | isEq] ++ [''Ord | isOrd])+ , v <- vs]+ cs <- typeConstructorsArgNames t+ asName <- newName "x"+ let generalizableExpr = mergeIFns $ foldr1 mergeI+ [ do retTypeOf <- lookupValN $ "-" ++ replicate (length ns) '>' ++ ":"+ let exprs = [[| expr $(varE n) |] | n <- ns]+ let conex = [| $(varE retTypeOf) $(conE c) $(varE asName) |]+ let root = [| value $(stringE $ showJustName c) $(conex) |]+ let rhs = foldl (\e1 e2 -> [| $e1 :$ $e2 |]) root exprs+ [d| instance Express $(return nt) where+ expr $(asP asName $ conP c (map varP ns)) = $rhs |]+ | (c,ns) <- cs+ ]+ cxt |=>| generalizableExpr++-- Not only really derive Express instances,+-- but cascade through argument types.+reallyDeriveExpressCascading :: Name -> DecsQ+reallyDeriveExpressCascading = reallyDeriveCascading ''Express reallyDeriveExpress
+ src/Data/Express/Fixtures.hs view
@@ -0,0 +1,1048 @@+-- |+-- Module : Data.Express.Fixtures+-- Copyright : (c) 2019 Rudy Matela+-- License : 3-Clause BSD (see the file LICENSE)+-- Maintainer : Rudy Matela <rudy@matela.com.br>+--+-- Defines some 'Expr' fixtures to facilitate testing and playing around on+-- the REPL (GHCI).+--+-- * Instead of having to write:+--+-- > > value "&&" (&&) :$ (value "not" not :$ val True) :$ val False+-- > not True && False :: Bool+--+-- Using this module, we can just write:+--+-- > > not' true -&&- false+-- > not True && False :: Bool+--+-- * Instead of having to write:+--+-- > > value "+" ((+)::Int->Int->Int) :$ (value "*" ((*)::Int->Int->Int) :$ var "x" (undefined::Int) :$ var "y" (undefined::Int)) :$ (value "*" ((*)::Int->Int->Int) :$ val (1::Int) :$ val (2::Int))+-- > x * y + 1 * 2 :: Int+--+-- Using this module, we can just write:+--+-- > > xx -*- yy -+- one -*- two+-- > x * y + 1 * 2 :: Int+--+-- * Instead of having to write:+--+-- > > value "||" (||) :$ (value "==" ((==)::Int->Int->Bool) :$ val (3::Int) :$ (value "+" ((+)::Int->Int->Int) :$ var "y" (undefined::Int) :$ val (1::Int))) :$ (value "not" not :$ val False)+-- > 3 == y + 1 || not False :: Bool+--+-- We can just write:+--+-- > > (three -==- yy -+- one) -||- not' false+-- > x == y + 1 || not False :: Bool+--+-- This exports over a hundred symbols+-- to be used mainly when writing unit tests+-- or playing around on GHCi.+--+-- Since the 'Expr' type only allows monomorphic values,+-- encoded polimorphic values are monomorphized+-- usually to the 'Int' type.+--+-- /Beware:/ lifted 'Expr' functions sometimes work for different types.+-- The current version does not have a rationale for types that are included:+-- you have to either try around on the REPL or look at the source to really know.+module Data.Express.Fixtures+ (+ -- * Convenience re-export+ module Data.Express++ -- * Functions and values encoded as Expr or functions of Exprs+ -- | The naming rules are:+ --+ -- * 'Int's are encoded using their English names,+ -- e.g.: 'zero', 'one', 'two';+ --+ -- * 'Char's are encoded using their English names,+ -- e.g.: 'bee', 'cee', 'dee';+ --+ -- * 0-argument constructors are encoded in lowercase,+ -- e.g.: 'false', 'true', 'nothing', 'just';+ --+ -- * lifted constructors are lowercased,+ -- e.g.: 'just';+ --+ -- * lifted functions are primed+ -- e.g.: 'id'', 'negate'', 'head'';+ --+ -- * lifted operators are surrounded by dashes,+ -- e.g.: '-+-', '-*-', '-&&-', '-||-', '-:-'.+ --+ -- * operators are encoded using their English names,+ -- e.g.: 'plus', 'times', 'cons';+ --+ -- * encoded functions are followed by @E@,+ -- e.g.: 'idE', 'notE', 'absE';+ --+ -- * variables have the first character duplicated,+ -- e.g.: 'xx', 'yy', 'xxs';+ --+ -- * encoded values may have the element type appended,+ -- e.g.: 'idInt', 'idBool', 'justInt', 'nilChar'.+ --+ -- Unqualified polymorphic constructors and functions+ -- have their element types bound to 'Int'.+ --+ -- There are exceptions to the above rules such as:+ -- when a name would conflict with a Prelude function.+ -- (e.g.: 'orE' and 'andE')++ -- ** Booleans+ , b_, pp, qq, rr, pp'+ , false+ , true+ , notE+ , orE+ , andE+ , implies+ , not'+ , (-||-)+ , (-&&-)+ , (-==>-)+ , (-==-)+ , (-/=-)+ , (-<=-)+ , (-<-)+ , compare'++ -- ** Integers+ , i_, xx, yy, zz, xx'+ , ii, jj, kk, ii'+ , zero, one, two, three, minusOne, minusTwo+ , idE, negateE, absE+ , idInt+ , idBool+ , idChar+ , idInts+ , idBools+ , idString+ , id', const', negate', abs'+ , plus, times+ , (-+-), (-*-)+ , ff, ffE+ , gg, ggE+ , (-?-)+ , (-$-)+ , odd'+ , even'++ -- ** Chars+ , c_+ , cc, dd, ccs+ , ae, bee, cee, dee+ , space, lineBreak+ , ord'+ , ordE++ -- ** Lists+ , is_+ , xxs+ , yys+ , nil+ , emptyString+ , nilInt+ , nilBool+ , nilChar+ , cons+ , consInt+ , consBool+ , consChar+ , (-:-)+ , unit+ , (-++-)+ , head'+ , tail'+ , length'+ , elem'+ , sort'+ , insert'++ -- ** Maybes+ , nothing+ , nothingInt+ , nothingBool+ , just+ , justInt+ , justBool++ -- ** Tuples+ , comma+ , pair+ , (-|-)+ , triple+ , quadruple+ , quintuple+ , sixtuple+ )+where++import Data.Express+import Data.Maybe+import Data.Typeable (Typeable, typeOf)+import Data.Char+import Data.List++int :: Int+int = undefined++bool :: Bool+bool = undefined++char :: Char+char = undefined++string :: String+string = undefined++-- | 'Expr' representing a hole of 'Bool' type.+--+-- > > b_+-- > _ :: Bool+b_ :: Expr+b_ = hole bool++-- | 'Expr' representing a variable @p :: `Bool`@.+--+-- > > pp+-- > p :: Bool+pp :: Expr+pp = var "p" bool++-- | 'Expr' representing a variable @q :: `Bool`@.+--+-- > > qq+-- > q :: Bool+qq :: Expr+qq = var "q" bool++-- | 'Expr' representing a variable @r :: `Bool`@.+--+-- > > rr+-- > r :: Bool+rr :: Expr+rr = var "r" bool++-- | 'Expr' representing a variable @p' :: `Bool`@.+--+-- > > pp'+-- > p' :: Bool+pp' :: Expr+pp' = var "p'" bool+++-- | 'False' encoded as an 'Expr'.+--+-- > > false+-- > False :: Bool+false :: Expr+false = val False++-- | 'True' encoded as an 'Expr'.+--+-- > > true+-- > True :: Bool+true :: Expr+true = val True++-- | The function 'not' encoded as an 'Expr'.+--+-- > > notE+-- > not :: Bool -> Bool+notE :: Expr+notE = value "not" not++-- | The function 'and' encoded as an 'Expr'.+--+-- > > andE+-- > (&&) :: Bool -> Bool -> Bool+andE :: Expr+andE = value "&&" (&&)++-- | The function 'or' encoded as an 'Expr'.+--+-- > > orE+-- > (||) :: Bool -> Bool -> Bool+orE :: Expr+orE = value "||" (||)++(-==>-) :: Expr -> Expr -> Expr+e1 -==>- e2 = implies :$ e1 :$ e2++implies :: Expr+implies = value "==>" (==>)+ where+ False ==> _ = True+ True ==> p = p++-- | The function 'not' lifted over the 'Expr' type.+--+-- > > not' false+-- > not False :: Bool+--+-- > > evalBool $ not' false+-- > True+--+-- > > not' pp+-- > not p :: Bool+not' :: Expr -> Expr+not' pp = notE :$ pp++-- | The function '&&' lifted over the 'Expr' type.+--+-- > > pp -&&- qq+-- > p && q :: Bool+--+-- > > false -&&- true+-- > False && True :: Bool+--+-- > > evalBool $ false -&&- true+-- > False+(-&&-) :: Expr -> Expr -> Expr+pp -&&- qq = andE :$ pp :$ qq++-- | The function '||' lifted over the 'Expr' type.+--+-- > > pp -||- qq+-- > p || q :: Bool+--+-- > > false -||- true+-- > False || True :: Bool+--+-- > > evalBool $ false -||- true+-- > True+(-||-) :: Expr -> Expr -> Expr+pp -||- qq = orE :$ pp :$ qq++-- | A typed hole of 'Int' type.+--+-- > > i_+-- > _ :: Int+i_ :: Expr+i_ = hole int++-- | A variable @x@ of 'Int' type.+--+-- > > xx+-- > x :: Int+xx :: Expr+xx = var "x" int++-- | A variable @y@ of 'Int' type.+--+-- > > yy+-- > y :: Int+yy :: Expr+yy = var "y" int++-- | A variable @z@ of 'Int' type.+--+-- > > zz+-- > z :: Int+zz :: Expr+zz = var "z" int++-- | A variable @x'@ of 'Int' type.+--+-- > > xx'+-- > x' :: Int+xx' :: Expr+xx' = var "x'" int++ii :: Expr+ii = var "i" int++jj :: Expr+jj = var "j" int++kk :: Expr+kk = var "k" int++ii' :: Expr+ii' = var "i'" int++-- | The value @0@ bound to the 'Int' type encoded as an 'Expr'.+--+-- > > zero+-- > 0 :: Int+zero :: Expr+zero = val (0 :: Int)++-- | The value @1@ bound to the 'Int' type encoded as an 'Expr'.+--+-- > > one+-- > 1 :: Int+one :: Expr+one = val (1 :: Int)++-- | The value @2@ bound to the 'Int' type encoded as an 'Expr'.+--+-- > > two+-- > 2 :: Int+two :: Expr+two = val (2 :: Int)++-- | The value @3@ bound to the 'Int' type encoded as an 'Expr'.+--+-- > > three+-- > 3 :: Int+three :: Expr+three = val (3 :: Int)++-- | The value @-1@ bound to the 'Int' type encoded as an 'Expr'.+--+-- > > minusOne+-- > -1 :: Int+minusOne :: Expr+minusOne = val (-1 :: Int)++-- | The value @-2@ bound to the 'Int' type encoded as an 'Expr'.+--+-- > > minusOne+-- > -2 :: Int+minusTwo :: Expr+minusTwo = val (-2 :: Int)++-- | A variable function @f@ of 'Int -> Int' type lifted over the 'Expr' type.+--+-- > > ff xx+-- > f x :: Int+--+-- > > ff one+-- > f 1 :: Int+ff :: Expr -> Expr+ff = (ffE :$)++-- | A variable @f@ of 'Int -> Int' type encoded as an 'Expr'.+--+-- > > ffE+-- > f :: Int -> Int+ffE :: Expr+ffE = var "f" (undefined :: Int -> Int)++-- | A variable function @g@ of 'Int -> Int' type lifted over the 'Expr' type.+--+-- > > gg yy+-- > g y :: Int+--+-- > > gg minusTwo+-- > gg (-2) :: Int+gg :: Expr -> Expr+gg = (ggE :$)++-- | A variable binary operator @?@ lifted over the 'Expr' type.+-- Works for 'Int', 'Bool', 'Char', @[Int]@ and 'String'.+--+-- > > xx -?- yy+-- > x ? y :: Int+--+-- > > pp -?- qq+-- > p ? q :: Bool+--+-- > > xx -?- qq+-- > *** Exception: (-?-): cannot apply `(?) :: * -> * -> *` to `x :: Int' and `q :: Bool'. Unhandled types?+(-?-) :: Expr -> Expr -> Expr+ex -?- ey = fromMaybe err $ ($$ ey) $ headOr err $ mapMaybe ($$ ex)+ [ var "?" (undefined :: Int -> Int -> Int)+ , var "?" (undefined :: Bool -> Bool -> Bool)+ , var "?" (undefined :: Char -> Char -> Char)+ , var "?" (undefined :: [Int] -> [Int] -> [Int])+ , var "?" (undefined :: String -> String -> String)+ ]+ where+ err = error $ "(-?-): cannot apply `(?) :: * -> * -> *` to `"+ ++ show ex ++ "' and `" ++ show ey ++ "'. Unhandled types?"++-- | A variable @g@ of 'Int -> Int' type encoded as an 'Expr'.+--+-- > > ggE+-- > g :: Int -> Int+ggE :: Expr+ggE = var "g" (undefined :: Int -> Int)++-- | The operator '+' for the 'Int' type for use on 'Expr's. (See also 'plus'.)+--+-- > > two -+- three+-- > 2 + 3 :: Int+--+-- > > minusOne -+- minusTwo -+- zero+-- > ((-1) + (-2)) + 0 :: Int+--+-- > > xx -+- (yy -+- zz)+-- > x + (y + z) :: Int+(-+-) :: Expr -> Expr -> Expr+e1 -+- e2 = plus :$ e1 :$ e2+infixl 6 -+-++-- | The operator '+' for the 'Int' type. (See also '-+-'.)+--+-- > > plus+-- > (+) :: Int -> Int -> Int+--+-- > > plus :$ one+-- > (1 +) :: Int -> Int+--+-- > > plus :$ xx :$ yy+-- > x + y :: Int+plus :: Expr+plus = value "+" ((+) :: Int -> Int -> Int)++-- | The operator '*' for the 'Int' type lifted over the 'Expr' type. (See also 'times'.)+--+-- > > three -*- three+-- > 9 :: Int+--+-- > > one -*- two -*- three+-- > (1 * 2) * 3 :: Int+--+-- > > two -*- xx+-- > 2 * x :: Int+(-*-) :: Expr -> Expr -> Expr+e1 -*- e2 = times :$ e1 :$ e2++-- | The operator '*' for the 'Int' type. (See also '-*-'.)+--+-- > > times+-- > (*) :: Int -> Int -> Int+--+-- > > times :$ two+-- > (2 *) :: Int -> Int+--+-- > > times :$ xx :$ yy+-- > x * y :: Int+times :: Expr+times = value "*" ((*) :: Int -> Int -> Int)++minus :: Expr+minus = value "-" ((-) :: Int -> Int -> Int)++-- | Constructs an application of 'id' as an 'Expr'.+-- Only works for 'Int', 'Bool', 'Char', 'String', @[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 :: Bool+id' :: Expr -> Expr+id' e = headOr err $ mapMaybe ($$ e)+ [ idInt+ , idBool+ , idChar+ , idInts+ , idBools+ , idString+ ]+ where+ err = error $ "id': unhandled type " ++ show (typ e)++-- | The function 'id' for the 'Int' type encoded as an 'Expr'. (See also 'id''.)+--+-- > > idE :$ xx+-- > id x :: Int+--+-- > > idE :$ zero+-- > id 0 :: Int+--+-- > > evaluate $ idE :$ zero :: Maybe Int+-- > Just 0+idE :: Expr+idE = idInt++-- | The function 'id' encoded as an 'Expr'. (cf. 'id'')+idInt,idBool,idChar,idInts,idBools,idString :: Expr+idInt = value "id" (id :: Id Int)+idBool = value "id" (id :: Id Bool)+idChar = value "id" (id :: Id Char)+idInts = value "id" (id :: Id [Int])+idBools = value "id" (id :: Id [Bool])+idString = value "id" (id :: Id String)+type Id a = a -> a++const' :: Expr -> Expr -> Expr+const' e1 e2 = (:$ e2) . headOr err $ mapMaybe ($$ e1)+ [ value "const" (const :: Int -> Int -> Int)+ , value "const" (const :: Bool -> Bool -> Bool)+ , value "const" (const :: Char -> Char -> Char)+ , value "const" (const :: [Int] -> [Int] -> [Int])+ , value "const" (const :: [Bool] -> [Bool] -> [Bool])+ , value "const" (const :: String -> String -> String)+ ]+ where+ err = error $ "const': unhandled type " ++ show (typ e1)++-- | 'negate' over the 'Int' type lifted over the 'Expr' type.+--+-- > > negate' xx+-- > negate x :: Int+--+-- > > evl (negate' one) :: Int+-- > -1+negate' :: Expr -> Expr+negate' e = negateE :$ e++-- | 'negate' over the 'Int' type encoded as an 'Expr'+--+-- > > negateE+-- > negate :: Int -> Int+negateE :: Expr+negateE = value "negate" (negate :: Int -> Int)++-- | 'abs' over the 'Int' type lifted over the 'Expr' type.+--+-- > > abs' xx'+-- > abs x' :: Int+--+-- > > evl (abs' minusTwo) :: Int+-- > 2+abs' :: Expr -> Expr+abs' e = absE :$ e++-- | 'abs' over the 'Int' type encoded as an 'Expr'.+--+-- > > absE+-- > abs :: Int -> Int+absE :: Expr+absE = value "abs" (abs :: Int -> Int)++odd' :: Expr -> Expr+odd' = (oddE :$) where oddE = value "odd" (odd :: Int -> Bool)++even' :: Expr -> Expr+even' = (evenE :$) where evenE = value "even" (even :: Int -> Bool)++-- | A hole of 'Char' type encoded as an 'Expr'.+--+-- > > c_+-- > _ :: Char+c_ :: Expr+c_ = hole char++cc :: Expr+cc = var "c" char++dd :: Expr+dd = var "d" char++ccs :: Expr+ccs = var "cs" [char]++-- The English name for letter 'a' is not really 'ae', but simply 'a'.+ae :: Expr+ae = val 'a'++-- | The character @\'b\'@ encoded as an 'Expr'+--+-- > > bee+-- > 'b' :: Char+--+-- > > evl bee :: Char+-- > 'b'+bee :: Expr+bee = val 'b'++-- | The character @\'c\'@ encoded as an 'Expr'+--+-- > > cee+-- > 'c' :: Char+--+-- > > evl cee :: Char+-- > 'c'+cee :: Expr+cee = val 'c'++-- | The character @\'d\'@ encoded as an 'Expr'+--+-- > > dee+-- > 'd' :: Char+--+-- > > evl dee :: Char+-- > 'd'+dee :: Expr+dee = val 'd'++space :: Expr+space = val ' '++lineBreak :: Expr+lineBreak = val '\n'++ord' :: Expr -> Expr+ord' = (ordE :$)++ordE :: Expr+ordE = value "ord" ord++-- | A typed hole of @[Int]@ type encoded as an 'Expr'.+--+-- > > is_+-- > _ :: [Int]+is_ :: Expr+is_ = hole [int]++-- | A variable named @xs@ of type @[Int]@ encoded as an 'Expr'.+--+-- > > xxs+-- > xs :: [Int]+xxs :: Expr+xxs = var "xs" [int]++-- | A variable named @ys@ of type @[Int]@ encoded as an 'Expr'.+--+-- > > yys+-- > ys :: [Int]+yys :: Expr+yys = var "ys" [int]++-- | An empty list of type @[Int]@ encoded as an 'Expr'.+--+-- > > nil+-- > [] :: [Int]+nil :: Expr+nil = nilInt++-- | An empty 'String' encoded as an 'Expr'.+--+-- > > emptyString+-- > "" :: String+emptyString :: Expr+emptyString = val ""++-- | The empty list '[]' encoded as an 'Expr'.+nilInt, nilBool, nilChar :: Expr+nilInt = val ([] :: [Int])+nilBool = val ([] :: [Bool])+nilChar = value "[]" ([] :: [Char])++-- | The list constructor with 'Int' as element type encoded as an 'Expr'.+--+-- > > cons+-- > (:) :: Int -> [Int] -> [Int]+--+-- > > cons :$ one :$ nil+-- > [1] :: [Int]+--+-- Consider using '-:-' and 'unit' when building lists of 'Expr'.+cons :: Expr+cons = consInt++-- | The list constructor @ : @ encoded as an 'Expr'.+consInt, consBool, consChar :: Expr+consInt = value ":" ((:) :: Cons Int)+consBool = value ":" ((:) :: Cons Bool)+consChar = value ":" ((:) :: Cons Char)+type Cons a = a -> [a] -> [a]++-- | 'unit' constructs a list with a single element.+-- This works for elements of type 'Int', 'Char' and 'Bool'.+--+-- > > unit one+-- > [1]+--+-- > > unit false+-- > [False]+unit :: Expr -> Expr+unit e = e -:- nil'+ where+ nil' | typ e == typ i_ = nil+ | typ e == typ c_ = emptyString+ | typ e == typ b_ = nilBool++-- | The list constructor lifted over the 'Expr' type.+-- Works for the element types 'Int', 'Char' and 'Bool'.+--+-- > > zero -:- one -:- unit two+-- > [0,1,2] :: [Int]+--+-- > > zero -:- one -:- two -:- nil+-- > [0,1,2] :: [Int]+--+-- > > bee -:- unit cee+-- > "bc" :: [Char]+(-:-) :: Expr -> Expr -> Expr+e1 -:- e2 = (:$ e2) . headOr err $ mapMaybe ($$ e1)+ [ consInt+ , consBool+ , consChar+ , value ":" ((:) :: Cons (Maybe Int))+ ]+ where+ err = error $ "(-:-): unhandled type " ++ show (typ e1)+infixr 5 -:-++-- | List concatenation lifted over the 'Expr' type.+-- Works for the element types 'Int', 'Char' and 'Bool'.+--+-- > > (zero -:- one -:- nil) -:- (two -:- three -:- nil)+-- > [0,1] -++- [2,3] :: [Int]+--+-- > > (bee -:- unit cee) -:- unit dee+-- > "bc" -++- "c" :: [Char]+(-++-) :: Expr -> Expr -> Expr+e1 -++- e2 = (:$ e2) . headOr err $ mapMaybe ($$ e1)+ [ value "++" ((++) :: [Int] -> [Int] -> [Int])+ , value "++" ((++) :: String -> String -> String)+ , value "++" ((++) :: [Bool] -> [Bool] -> [Bool])+ ]+ where+ err = error $ "(-++-): unhandled type " ++ show (typ e1)+infixr 5 -++-++-- | List 'head' lifted over the 'Expr' type.+-- Works for the element types 'Int', 'Char' and 'Bool'.+--+-- > > 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+-- > 1+head' :: Expr -> Expr+head' exs = headOr err $ mapMaybe ($$ exs)+ [ value "head" (head :: [Int] -> Int)+ , value "head" (head :: [Char] -> Char)+ , value "head" (head :: [Bool] -> Bool)+ ]+ where+ err = error $ "head': cannot apply `head :: [a] -> a` to `" ++ show exs ++ "'."++-- | List 'tail' lifted over the 'Expr' type.+-- Works for the element types 'Int', 'Char' and 'Bool'.+--+-- > > 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]+tail' :: Expr -> Expr+tail' exs = headOr err $ mapMaybe ($$ exs)+ [ value "tail" (tail :: [Int] -> [Int])+ , value "tail" (tail :: [Char] -> [Char])+ , value "tail" (tail :: [Bool] -> [Bool])+ ]+ where+ err = error $ "tail': unhandled type " ++ show (typ exs)++-- | List 'length' lifted over the 'Expr' type.+-- Works for the element types 'Int', 'Char' and 'Bool'.+--+-- > > length' $ unit one+-- > length [1] :: Int+--+-- > > length' $ unit bee+-- > length "b" :: Int+--+-- > > length' $ zero -:- unit two+-- > length [0,2] :: Int+--+-- > > evl $ length' $ unit one :: Int+-- > 1+length' :: Expr -> Expr+length' exs = headOr err $ mapMaybe ($$ exs)+ [ value "length" (length :: [Int] -> Int)+ , value "length" (length :: [Char] -> Int)+ , value "length" (length :: [Bool] -> Int)+ ]+ where+ err = error $ "length': cannot apply `length :: [a] -> a` to `" ++ show exs ++ "'."++sort' :: Expr -> Expr+sort' exs = headOr err $ mapMaybe ($$ exs)+ [ value "sort" (sort :: [Int] -> [Int])+ , value "sort" (sort :: [Char] -> [Char])+ , value "sort" (sort :: [Bool] -> [Bool])+ ]+ where+ err = error $ "sort': unhandled type " ++ show (typ exs)++insert' :: Expr -> Expr -> Expr+insert' ex exs = (:$ exs) . headOr err $ mapMaybe ($$ ex)+ [ value "insert" (insert :: Int -> [Int] -> [Int])+ , value "insert" (insert :: Bool -> [Bool] -> [Bool])+ , value "insert" (insert :: Char -> String -> String)+ ]+ where+ err = error $ "insert': unhandled type " ++ show (typ ex)++elem' :: Expr -> Expr -> Expr+elem' ex exs = (:$ exs) . headOr err $ mapMaybe ($$ ex)+ [ value "elem" (elem :: Int -> [Int] -> Bool)+ , value "elem" (elem :: Bool -> [Bool] -> Bool)+ , value "elem" (elem :: Char -> String -> Bool)+ ]+ where+ err = error $ "elem': unhandled type " ++ show (typ ex)++(-$-) :: Expr -> Expr -> Expr+ef -$- ex = (:$ ex) . headOr err $ mapMaybe ($$ ef)+ [ value "$" (($) :: Apply Int)+ , value "$" (($) :: Apply Bool)+ , value "$" (($) :: Apply Char)+ , value "$" (($) :: Apply [Int])+ , value "$" (($) :: Apply [Bool])+ , value "$" (($) :: Apply [Char])+ ]+ where+ err = error $ "(-$-): unhandled type " ++ show (typ ef)+infixl 6 -$-+type Apply a = (a -> a) -> a -> a++(-==-) :: Expr -> Expr -> Expr+ex -==- ey = (:$ ey) . headOr err $ mapMaybe ($$ ex)+ [ value "==" ((==) :: Comparison ())+ , value "==" ((==) :: Comparison Int)+ , value "==" ((==) :: Comparison Bool)+ , value "==" ((==) :: Comparison Char)+ , value "==" ((==) :: Comparison [Int])+ , value "==" ((==) :: Comparison [Bool])+ , value "==" ((==) :: Comparison [Char])+ ]+ where+ err = error $ "(-==-): unhandled type " ++ show (typ ex)+infix 4 -==-+type Comparison a = a -> a -> Bool++(-/=-) :: Expr -> Expr -> Expr+ex -/=- ey = (:$ ey) . headOr err $ mapMaybe ($$ ex)+ [ value "/=" ((/=) :: Comparison ())+ , value "/=" ((/=) :: Comparison Int)+ , value "/=" ((/=) :: Comparison Bool)+ , value "/=" ((/=) :: Comparison Char)+ , value "/=" ((/=) :: Comparison [Int])+ , value "/=" ((/=) :: Comparison [Bool])+ , value "/=" ((/=) :: Comparison [Char])+ ]+ where+ err = error $ "(-/=-): unhandled type " ++ show (typ ex)+infix 4 -/=-++(-<=-) :: Expr -> Expr -> Expr+ex -<=- ey = (:$ ey) . headOr err $ mapMaybe ($$ ex)+ [ value "<=" ((<=) :: Comparison ())+ , value "<=" ((<=) :: Comparison Int)+ , value "<=" ((<=) :: Comparison Bool)+ , value "<=" ((<=) :: Comparison Char)+ , value "<=" ((<=) :: Comparison [Int])+ , value "<=" ((<=) :: Comparison [Bool])+ , value "<=" ((<=) :: Comparison [Char])+ ]+ where+ err = error $ "(-<=-): unhandled type " ++ show (typ ex)+infix 4 -<=-++(-<-) :: Expr -> Expr -> Expr+ex -<- ey = (:$ ey) . headOr err $ mapMaybe ($$ ex)+ [ value "<" ((<) :: Comparison ())+ , value "<" ((<) :: Comparison Int)+ , value "<" ((<) :: Comparison Bool)+ , value "<" ((<) :: Comparison Char)+ , value "<" ((<) :: Comparison [Int])+ , value "<" ((<) :: Comparison [Bool])+ , value "<" ((<) :: Comparison [Char])+ ]+ where+ err = error $ "(-<-): unhandled type " ++ show (typ ex)+infix 4 -<-++compare' :: Expr -> Expr -> Expr+compare' ex ey = (:$ ey) . headOr err $ mapMaybe ($$ ex)+ [ value "compare" (compare :: Compare ())+ , value "compare" (compare :: Compare Int)+ , value "compare" (compare :: Compare Bool)+ , value "compare" (compare :: Compare Char)+ , value "compare" (compare :: Compare [Int])+ , value "compare" (compare :: Compare [Bool])+ , value "compare" (compare :: Compare [Char])+ ]+ where+ err = error $ "(-<-): unhandled type " ++ show (typ ex)+type Compare a = a -> a -> Ordering++nothing :: Expr+nothing = nothingInt++nothingInt, nothingBool :: Expr+nothingInt = val (Nothing :: Maybe Int)+nothingBool = val (Nothing :: Maybe Bool)++justInt, justBool :: Expr+justInt = value "Just" (Just :: Just Int)+justBool = value "Just" (Just :: Just Bool)+type Just a = a -> Maybe a++just :: Expr -> Expr+just ex = headOr err $ mapMaybe ($$ ex)+ [ justInt+ , justBool+ ]+ where+ err = error $ "just: unhandled type " ++ show (typ ex)++(-|-) :: Expr -> Expr -> Expr+(-|-) = pair++pair :: Expr -> Expr -> Expr+pair x y = comma :$ x :$ y+ where+ comma = case (show $ typ x, show $ typ y) of+ ("Int", "Int") -> value "," ((,) :: Pair Int Int)+ ("Int", "Bool") -> value "," ((,) :: Pair Int Bool)+ ("Bool","Int") -> value "," ((,) :: Pair Bool Int)+ ("Bool","Bool") -> value "," ((,) :: Pair Bool Bool)+ (t,t') -> error $ "(-:-): unhandled types " ++ t ++ " " ++ t'+type Pair a b = a -> b -> (a,b)++comma :: Expr+comma = value "," ((,) :: Pair Int Int)++triple :: Expr -> Expr -> Expr -> Expr+triple e1 e2 e3 = ccE :$ e1 :$ e2 :$ e3+ where+ ccE = value ",," ((,,) :: Int -> Int -> Int -> (Int,Int,Int))++quadruple :: Expr -> Expr -> Expr -> Expr -> Expr+quadruple e1 e2 e3 e4 = cccE :$ e1 :$ e2 :$ e3 :$ e4+ where+ cccE = value ",,," ((,,,) :: Int -> Int -> Int -> Int -> (Int,Int,Int,Int))++quintuple :: Expr -> Expr -> Expr -> Expr -> Expr -> Expr+quintuple e1 e2 e3 e4 e5 = ccccE :$ e1 :$ e2 :$ e3 :$ e4 :$ e5+ where+ ccccE = value ",,,," ((,,,,) :: Int -> Int -> Int -> Int -> Int -> (Int,Int,Int,Int,Int))++sixtuple :: Expr -> Expr -> Expr -> Expr -> Expr -> Expr -> Expr+sixtuple e1 e2 e3 e4 e5 e6 = cccccE :$ e1 :$ e2 :$ e3 :$ e4 :$ e5 :$ e6+ where+ cccccE = value ",,,,," ((,,,,,) :: Int -> Int -> Int -> Int -> Int -> Int -> (Int,Int,Int,Int,Int,Int))++headOr :: a -> [a] -> a+headOr x [] = x+headOr _ (x:_) = x
+ src/Data/Express/Fold.hs view
@@ -0,0 +1,133 @@+-- |+-- Module : Data.Express.Fold+-- Copyright : (c) 2019 Rudy Matela+-- License : 3-Clause BSD (see the file LICENSE)+-- Maintainer : Rudy Matela <rudy@matela.com.br>+--+-- Defines utilities for folding and unfolding 'Expr's.+{-# LANGUAGE DeriveDataTypeable #-} -- for GHC <= 7.8+module Data.Express.Fold+ ( fold+ , unfold+ , foldPair+ , unfoldPair+ , foldTrio+ , unfoldTrio+ , foldApp+ , unfoldApp+ )+where++import Data.Express.Core+import Data.Typeable (Typeable) -- for GHC <= 7.8++data ExprPair = ExprPair+ deriving Typeable -- for GHC <= 7.8++-- | /O(n)/.+-- Folds a list of 'Expr' with function application (':$').+-- This reverses the effect of 'unfoldApp'.+--+-- > 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 ':$' 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.+foldApp :: [Expr] -> Expr+foldApp = foldl1 (:$)++-- | /O(1)/.+-- Folds a pair of 'Expr' values into a single 'Expr'.+-- (cf. 'unfoldPair')+--+-- 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 #+--+-- This is useful when applying transformations on pairs of 'Expr's, such as+-- 'Data.Express.Canon.canonicalize',+-- 'Data.Express.Map.mapValues' or+-- 'Data.Express.Canon.canonicalVariations'.+--+-- > > let ii = var "i" (undefined::Int)+-- > > let kk = var "k" (undefined::Int)+-- > > unfoldPair $ canonicalize $ foldPair (ii,kk)+-- > (x :: Int,y :: Int)+foldPair :: (Expr,Expr) -> Expr+foldPair (e1,e2) = value "," (undefined :: ExprPair) :$ e1 :$ e2++-- | /O(1)/.+-- Unfolds an 'Expr' representing a pair.+-- This reverses the effect of 'foldPair'.+--+-- > > 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)+unfoldPair :: Expr -> (Expr,Expr)+unfoldPair (Value "," _ :$ e1 :$ e2) = (e1,e2)+unfoldPair (Value "(,)" _ :$ e1 :$ e2) = (e1,e2)+unfoldPair _ = error "unfoldPair: not an Expr pair"++data ExprTrio = ExprTrio+ deriving Typeable -- for GHC <= 7.8++foldTrio :: (Expr,Expr,Expr) -> Expr+foldTrio (e1,e2,e3) = value ",," (undefined :: ExprTrio) :$ e1 :$ e2 :$ e3++unfoldTrio :: Expr -> (Expr,Expr,Expr)+unfoldTrio (Value ",," _ :$ e1 :$ e2 :$ e3) = (e1,e2,e3)+unfoldTrio (Value "(,,)" _ :$ e1 :$ e2 :$ e3) = (e1,e2,e3)+unfoldTrio _ = error "unfoldTrio: not an Expr trio"++data ExprList = ExprList+ deriving Typeable -- for GHC <= 7.8++-- | /O(n)/.+-- Folds a list of 'Expr's into a single 'Expr'.+-- (cf. 'unfold')+--+-- This /always/ generates an ill-typed expression.+--+-- > fold [val False, val True, val (1::Int)]+-- > [False,True,1] :: ill-typed # ExprList $ Bool #+--+-- This is useful when applying transformations on lists of 'Expr's, such as+-- 'Data.Express.Canon.canonicalize',+-- 'Data.Express.Map.mapValues' or+-- 'Data.Express.Canon.canonicalVariations'.+--+-- > > 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]+fold :: [Expr] -> Expr+fold [] = value "[]" ExprList+fold (e:es) = value ":" ExprList :$ e :$ fold es++-- | /O(n)/.+-- Unfolds an 'Expr' representing a list into a list of 'Expr's.+-- This reverses the effect of 'fold'.+--+-- > > expr [1,2,3::Int]+-- > [1,2,3] :: [Int]+-- > > unfold $ expr [1,2,3::Int]+-- > [1 :: Int,2 :: Int,3 :: Int]+unfold :: Expr -> [Expr]+unfold (Value "[]" _) = []+unfold (((Value ":" _) :$ e) :$ es) = e : unfold es+unfold e = error $ "unfold: cannot unfold expression: " ++ show e
+ src/Data/Express/Hole.hs view
@@ -0,0 +1,180 @@+-- |+-- Module : Data.Express.Hole+-- Copyright : (c) 2019 Rudy Matela+-- License : 3-Clause BSD (see the file LICENSE)+-- Maintainer : Rudy Matela <rudy@matela.com.br>+--+-- Utilities for manipulating variables and typed holes encoded as 'Expr's.+{-# LANGUAGE CPP #-}+module Data.Express.Hole+ (+ -- * Creating variables+ varAsTypeOf+ , listVars+ , listVarsAsTypeOf++ -- * Typed holes+ , hole+ , isHole+ , holes+ , nubHoles+ , holeAsTypeOf+ )+where++import Data.Express.Core++import Data.Dynamic+import Data.Maybe (fromMaybe)+import Data.Express.Utils.Typeable (tyArity)+import Data.Express.Utils.List (nubSort)+import Data.Express.Utils.String (variableNamesFromTemplate)++-- | /O(1)/.+-- Creates a 'var'iable with the same type as the given 'Expr'.+--+-- > > let one = val (1::Int)+-- > > "x" `varAsTypeOf` one+-- > x :: Int+--+-- > > "p" `varAsTypeOf` val False+-- > p :: Bool+varAsTypeOf :: String -> Expr -> Expr+varAsTypeOf n = Value ('_':n) . undefine . fromMaybe err . toDynamic+ where+ err = error "varAsTypeOf: could not compile Dynamic value, type error?"+ undefine :: Dynamic -> Dynamic+#if __GLASGOW_HASKELL__ >= 806+ undefine (Dynamic t v) = (Dynamic t undefined)+#else+ undefine = id -- there's no way to do this using the old Data.Dynamic API.+#endif++-- | /O(1)/.+-- Creates an 'Expr' representing a typed hole with the type of the given+-- 'Expr'. (cf. 'hole')+--+-- > > val (1::Int)+-- > 1 :: Int+-- > > holeAsTypeOf $ val (1::Int)+-- > _ :: Int+holeAsTypeOf :: Expr -> Expr+holeAsTypeOf = ("" `varAsTypeOf`)++-- | /O(1)/.+-- Creates an 'Expr' representing a typed hole of the given argument type.+--+-- > > hole (undefined :: Int)+-- > _ :: Int+--+-- > > 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 "_" x+hole :: Typeable a => a -> Expr+hole a = var "" (undefined `asTypeOf` a)++-- | /O(1)/.+-- Checks if an 'Expr' represents a typed hole.+-- (cf. 'hole')+--+-- > > isHole $ hole (undefined :: Int)+-- > True+--+-- > > isHole $ value "not" not :$ val True+-- > False+--+-- > > isHole $ val 'a'+-- > False+isHole :: Expr -> Bool+isHole (Value "_" _) = True+isHole _ = False++-- | /O(n)/.+-- Lists all holes in an expression, in order and with repetitions.+-- (cf. 'nubHoles')+--+-- > > 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]+holes :: Expr -> [Expr]+holes = filter isHole . values++-- | /O(n log n)/.+-- Lists all holes in an expression without repetitions.+-- (cf. 'holes')+--+-- > > 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]+nubHoles :: Expr -> [Expr]+nubHoles = nubSort . holes++-- |+-- Generate an infinite list of variables+-- based on a template and a given type.+-- (cf. 'listVarsAsTypeOf')+--+-- > > 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+-- > , ...+-- > ]+listVars :: Typeable a => String -> a -> [Expr]+listVars s a = map (`var` a) (variableNamesFromTemplate s)++-- |+-- Generate an infinite list of variables+-- based on a template+-- and the type of a given 'Expr'.+-- (cf. 'listVars')+--+-- > > 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+-- > , ...+-- > ]+listVarsAsTypeOf :: String -> Expr -> [Expr]+listVarsAsTypeOf s e = map (`varAsTypeOf` e) (variableNamesFromTemplate s)
+ src/Data/Express/Instances.hs view
@@ -0,0 +1,359 @@+-- |+-- Module : Data.Express.Instances+-- Copyright : (c) 2019 Rudy Matela+-- License : 3-Clause BSD (see the file LICENSE)+-- Maintainer : Rudy Matela <rudy@matela.com.br>+--+-- Defines utilities do deal with instances of typeclasses+module Data.Express.Instances+ ( reifyEq+ , reifyOrd+ , reifyEqOrd+ , reifyName++ , mkEq+ , mkOrd+ , mkOrdLessEqual+ , mkName+ , mkNameWith++ , isEq+ , isOrd+ , isEqOrd+ , isEqT+ , isOrdT+ , isEqOrdT++ , mkEquation+ , mkComparisonLE+ , mkComparisonLT+ , mkComparison+ , lookupComparison++ , listVarsWith+ , lookupName+ , lookupNames++ , validApps+ , findValidApp++ , preludeNameInstances+ )+where++-- TODO: document and test functions of the Instances module++import Data.Express.Basic+import Data.Express.Name+import Data.Express.Express+import Data.Express.Utils.Typeable+import Data.Express.Utils.List+import Data.Maybe+import Control.Applicative ((<$>)) -- for GHC <= 7.8+++-- reifying instances --++-- | /O(1)./+-- Reifies an 'Eq' instance into a list of 'Expr's.+-- The list will contain '==' and '/=' for the given type.+-- (cf. 'mkEq', 'mkEquation')+--+-- > > 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 ]+reifyEq :: (Typeable a, Eq a) => a -> [Expr]+reifyEq a = mkEq ((==) -:> a)++-- | /O(1)./+-- Reifies an 'Ord' instance into a list of 'Expr's.+-- The list will contain 'compare', '<=' and '<' for the given type.+-- (cf. 'mkOrd', 'mkOrdLessEqual', 'mkComparisonLE', 'mkComparisonLT')+--+-- > > 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 ]+reifyOrd :: (Typeable a, Ord a) => a -> [Expr]+reifyOrd a = mkOrd (compare -:> a)++-- | /O(1)./+-- Reifies 'Eq' and 'Ord' instances into a list of 'Expr'.+reifyEqOrd :: (Typeable a, Ord a) => a -> [Expr]+reifyEqOrd a = reifyEq a ++ reifyOrd a++-- | /O(1)./+-- Reifies a 'Name' instance into a list of 'Expr's.+-- The list will contain 'name' for the given type.+-- (cf. 'mkName', 'lookupName', 'lookupNames')+--+-- > > reifyName (undefined :: Int)+-- > [name :: Int -> [Char]]+--+-- > > reifyName (undefined :: Bool)+-- > [name :: Bool -> [Char]]+reifyName :: (Typeable a, Name a) => a -> [Expr]+reifyName a = mkName (name -:> a)++-- todo: reifyExpr and related functions++-- | /O(1)/.+-- Builds a reified 'Eq' instance from the given '==' function.+-- (cf. 'reifyEq')+--+-- > > mkEq ((==) :: Int -> Int -> Bool)+-- > [ (==) :: Int -> Int -> Bool+-- > , (/=) :: Int -> Int -> Bool ]+mkEq :: Typeable a => (a -> a -> Bool) -> [Expr]+mkEq (==) =+ [ value "==" (==)+ , value "/=" (/=)+ ]+ where+ x /= y = not (x == y)++-- | /O(1)/.+-- Builds a reified 'Ord' instance from the given 'compare' function.+-- (cf. 'reifyOrd', 'mkOrdLessEqual')+mkOrd :: Typeable a => (a -> a -> Ordering) -> [Expr]+mkOrd compare =+ [ value "<=" (<=)+ , value "<" (<)+-- we don't include other Ord functions, at least for now+--, value "compare" compare+ ]+ where+ x < y = x `compare` y == LT+ x <= y = x `compare` y /= GT++-- | /O(1)/.+-- Builds a reified 'Ord' instance from the given '<=' function.+-- (cf. 'reifyOrd', 'mkOrd')+mkOrdLessEqual :: Typeable a => (a -> a -> Bool) -> [Expr]+mkOrdLessEqual (<=) =+ [ value "<=" (<=)+ , value "<" (<)+ ]+ where+ x < y = not (y <= x)++-- | /O(1)/.+-- Builds a reified 'Name' instance from the given 'name' function.+-- (cf. 'reifyName', 'mkNameWith')+mkName :: Typeable a => (a -> String) -> [Expr]+mkName name = [value "name" name]++-- | /O(1)/.+-- Builds a reified 'Name' instance from the given 'String' and type.+-- (cf. 'reifyName', 'mkName')+mkNameWith :: Typeable a => String -> a -> [Expr]+mkNameWith n a = [value "name" (const n -:> a)]+++-- searching for functions --++lookupComparison :: String -> TypeRep -> [Expr] -> Maybe Expr+lookupComparison n' t = find (\i@(Value n _) -> n == n' && typ i == mkComparisonTy t)++-- | /O(n)./+-- Returns whether an 'Eq' instance exists in the given instances list+-- for the given 'TypeRep'.+--+-- > > 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)/.+isEqT :: [Expr] -> TypeRep -> Bool+isEqT is t = isJust $ lookupComparison "==" t is++-- | /O(n)./+-- Returns whether an 'Ord' instance exists in the given instances list+-- for the given 'TypeRep'.+--+-- > > 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)/.+isOrdT :: [Expr] -> TypeRep -> Bool+isOrdT is t = isJust $ lookupComparison "<=" t is++-- | /O(n)./+-- Returns whether both 'Eq' and 'Ord' instance exist in the given list+-- for the given 'TypeRep'.+--+-- Given that the instances list has length /n/, this function is /O(n)/.+isEqOrdT :: [Expr] -> TypeRep -> Bool+isEqOrdT is t = isEqT is t && isOrdT is t++-- | /O(n+m)./+-- Returns whether an 'Eq' instance exists in the given instances list+-- for the given 'Expr'.+--+-- > > 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 'Expr' has size /n/,+-- this function is /O(n+m)/.+isEq :: [Expr] -> Expr -> Bool+isEq is = isEqT is . typ++-- | /O(n+m)./+-- Returns whether an 'Ord' instance exists in the given instances list+-- for the given 'Expr'.+--+-- > > 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 'Expr' has size /n/,+-- this function is /O(n+m)/.+isOrd :: [Expr] -> Expr -> Bool+isOrd is = isOrdT is . typ++-- | /O(n+m)./+-- Returns whether both 'Eq' and 'Ord' instance exist in the given list+-- for the given 'Expr'.+--+-- Given that the instances list has length /m/+-- and that the given 'Expr' has size /n/,+-- this function is /O(n+m)/.+isEqOrd :: [Expr] -> Expr -> Bool+isEqOrd is e = isEq is e && isOrd is e++mkComparison :: String -> [Expr] -> Expr -> Expr -> Expr+mkComparison n' is e1 e2 = fromMaybe (val False) $ do+ e1e <- findValidApp os e1+ e1e $$ e2+ where+ os = [eq | eq@(Value n _) <- is, n == n']++mkEquation :: [Expr] -> Expr -> Expr -> Expr+mkEquation = mkComparison "=="++mkComparisonLT :: [Expr] -> Expr -> Expr -> Expr+mkComparisonLT = mkComparison "<"++mkComparisonLE :: [Expr] -> Expr -> Expr -> Expr+mkComparisonLE = mkComparison "<="++lookupName :: [Expr] -> Expr -> String+lookupName is e = fromMaybe "x" $ eval "x" <$> findValidApp es e+ where+ es = [e | e@(Value "name" _) <- is]++lookupNames :: [Expr] -> Expr -> [String]+lookupNames is = variableNamesFromTemplate . lookupName is++listVarsWith :: [Expr] -> Expr -> [Expr]+listVarsWith is e = lookupName is e `listVarsAsTypeOf` e+++-- helpers --++validApps :: [Expr] -> Expr -> [Expr]+validApps es e = mapMaybe ($$ e) es++findValidApp :: [Expr] -> Expr -> Maybe Expr+findValidApp es = listToMaybe . validApps es++(-:>) :: (a -> b) -> a -> (a -> b)+(-:>) = const+infixl 1 -:>+++-- reified instances --++preludeNameInstances :: [Expr]+preludeNameInstances = concat+ [ reifyName (u :: ())+ , reifyName (u :: Bool)+ , reifyName (u :: Int)+ , reifyName (u :: Integer)+ , reifyName (u :: Char)+ , reifyName (u :: Ordering)+ , reifyName (u :: Rational)+ , reifyName (u :: Float)+ , reifyName (u :: Double)++ , reifyName (u :: [()])+ , reifyName (u :: [Bool])+ , reifyName (u :: [Int])+ , reifyName (u :: [Integer])+ , reifyName (u :: [Char])+ , reifyName (u :: [Ordering])+ , reifyName (u :: [Rational])+ , reifyName (u :: [Float])+ , reifyName (u :: [Double])++ , reifyName (u :: Maybe ())+ , reifyName (u :: Maybe Bool)+ , reifyName (u :: Maybe Int)+ , reifyName (u :: Maybe Integer)+ , reifyName (u :: Maybe Char)+ , reifyName (u :: Maybe Ordering)+ , reifyName (u :: Maybe Rational)+ , reifyName (u :: Maybe Float)+ , reifyName (u :: Maybe Double)++ , reifyName (u :: ((),()))+ , reifyName (u :: (Bool,Bool))+ , reifyName (u :: (Int,Int))+ , reifyName (u :: (Integer,Integer))+ , reifyName (u :: (Char,Char))+ , reifyName (u :: (Ordering,Ordering))+ , reifyName (u :: (Rational,Rational))+ , reifyName (u :: (Float,Float))+ , reifyName (u :: (Double,Double))++ , reifyName (u :: () -> ())+ , reifyName (u :: Bool -> Bool)+ , reifyName (u :: Int -> Int)+ , reifyName (u :: Integer -> Integer)+ , reifyName (u :: Char -> Char)+ , reifyName (u :: Ordering -> Ordering)+ , reifyName (u :: Rational -> Rational)+ , reifyName (u :: Float -> Float)+ , reifyName (u :: Double -> Double)++ , reifyName (u :: () -> () -> ())+ , reifyName (u :: Bool -> Bool -> Bool)+ , reifyName (u :: Int -> Int -> Int)+ , reifyName (u :: Integer -> Integer -> Integer)+ , reifyName (u :: Char -> Char -> Char)+ , reifyName (u :: Ordering -> Ordering -> Ordering)+ , reifyName (u :: Rational -> Rational -> Rational)+ , reifyName (u :: Float -> Float -> Float)+ , reifyName (u :: Double -> Double -> Double)+ ]+ where+ u :: a+ u = undefined+
+ src/Data/Express/Map.hs view
@@ -0,0 +1,245 @@+-- |+-- Module : Data.Express.Map+-- Copyright : (c) 2019 Rudy Matela+-- License : 3-Clause BSD (see the file LICENSE)+-- Maintainer : Rudy Matela <rudy@matela.com.br>+--+-- Utilities for mapping or transforming 'Expr's.+module Data.Express.Map+ ( mapValues+ , mapVars+ , mapConsts+ , mapSubexprs+ , (//-)+ , (//)+ , renameVarsBy+ )+where++import Data.Express.Core+import Data.Express.Utils.List+import Data.Maybe (fromMaybe)++-- | /O(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 e+--+-- Then:+--+-- > > 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)/.+mapValues :: (Expr -> Expr) -> Expr -> Expr+mapValues f = m+ where+ m (e1 :$ e2) = m e1 :$ m e2+ m e = f e++-- | /O(n*m)/.+-- 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 :$ yy+--+-- Then:+--+-- > > 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)/.+mapVars :: (Expr -> Expr) -> Expr -> Expr+mapVars f = mapValues f'+ where+ f' e = if isVar e+ then f e+ else e++-- | /O(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 e+--+-- Then:+--+-- > > 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)/.+mapConsts :: (Expr -> Expr) -> Expr -> Expr+mapConsts f = mapValues f'+ where+ f' e = if isConst e+ then f e+ else e++-- | /O(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 _ = Nothing+--+-- Then:+--+-- > > mapSubexprs pluswap $ (xx -*- yy) -+- (yy -*- zz)+-- > y * z + x * y :: Int+--+-- > > mapSubexprs pluswap $ (xx -+- yy) -*- (yy -+- zz)+-- > (y + x) * (z + y) :: Int+--+-- Substitutions 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)/.+mapSubexprs :: (Expr -> Maybe Expr) -> Expr -> Expr+mapSubexprs f = m+ where+ m e = fromMaybe e' (f e)+ where+ e' = case e of+ e1 :$ e2 -> m e1 :$ m e2+ e -> e++-- | /O(n*m)/.+-- Substitute occurrences of values in an expression+-- from the given list of substitutions.+-- (cf. 'mapValues')+--+-- 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 :$ yy+--+-- Then:+--+-- > > ((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) :: Int+--+-- This function does not work for substituting non-terminal subexpressions:+--+-- > > (xx -+- yy) //- [(xx -+- yy, zz)]+-- > x + y :: Int+--+-- Please 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)/.+(//-) :: Expr -> [(Expr,Expr)] -> Expr+e //- s = mapValues (flip lookupId s) e++-- | /O(n*n*m)/.+-- Substitute subexpressions in an expression+-- from the given list of substitutions.+-- (cf. 'mapSubexprs').+--+-- 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 :$ yy+--+-- Then:+--+-- > > ((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) :: Int+--+-- Replacement 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)/ in the worst case,+-- and we may need to compare with /n/ subexpressions in the worst case.+(//) :: Expr -> [(Expr,Expr)] -> Expr+e // s = mapSubexprs (flip lookup s) e++-- | Rename variables in an 'Expr'.+--+-- > > 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) :: Int+--+-- NOTE: this will affect holes!+renameVarsBy :: (String -> String) -> Expr -> Expr+renameVarsBy f = mapValues f'+ where+ f' (Value ('_':n) t) = Value ('_':f n) t+ f' e = e
+ src/Data/Express/Match.hs view
@@ -0,0 +1,118 @@+-- |+-- Module : Data.Express.Match+-- Copyright : (c) 2019 Rudy Matela+-- License : 3-Clause BSD (see the file LICENSE)+-- Maintainer : Rudy Matela <rudy@matela.com.br>+--+-- Utilities for matching 'Expr's with 'var'iables.+module Data.Express.Match+ ( match+ , matchWith+ , isInstanceOf+ , hasInstanceOf+ , isSubexprOf+ )+where++import Data.Express.Basic+import Data.Maybe+import Data.Functor ((<$>))+import Control.Monad ((>=>))++-- |+-- Given two expressions, returns a 'Just' list of matches+-- of subexpressions of the first expressions+-- to variables in the second expression.+-- Returns 'Nothing' 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)) = Nothing+match :: Expr -> Expr -> Maybe [(Expr,Expr)]+match = matchWith []++-- |+-- Like 'match' but allowing predefined bindings.+--+-- > matchWith [(xx,zero)] (zero -+- one) (xx -+- yy) = Just [(xx,zero), (yy,one)]+-- > matchWith [(xx,one)] (zero -+- one) (xx -+- yy) = Nothing+matchWith :: [(Expr,Expr)] -> Expr -> Expr -> Maybe [(Expr,Expr)]+matchWith bs e1' e2' = m e1' e2' bs+ where+ m :: Expr -> Expr -> [(Expr,Expr)] -> Maybe [(Expr,Expr)]+ m (f1 :$ x1) (f2 :$ x2) = m f1 f2 >=> m x1 x2+ m e1 e2+ | isVar e2 && mtyp e1 == mtyp e2 = updateAssignments (e2,e1)+ | e1 == e2 = Just+ | otherwise = const Nothing++updateAssignments :: (Expr,Expr) -> [(Expr,Expr)] -> Maybe [(Expr,Expr)]+updateAssignments (e,e') = \bs ->+ case lookup e bs of+ Nothing -> Just ((e,e'):bs)+ Just e'' -> if e'' == e'+ then Just bs+ else Nothing++-- |+-- Given two 'Expr's,+-- checks if the first expression+-- is an instance of the second+-- in terms of variables.+-- (cf. 'hasInstanceOf')+--+-- > > 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) = False+isInstanceOf :: Expr -> Expr -> Bool+e1 `isInstanceOf` e2 = isJust $ e1 `match` e2++-- |+-- Checks if any of the subexpressions of the first argument 'Expr'+-- is an instance of the second argument 'Expr'.+hasInstanceOf :: Expr -> Expr -> Bool+e1 `hasInstanceOf` e2 = any (`isInstanceOf` e2) (subexprs e1)++-- | /O(n^2)/.+-- Checks if an 'Expr' is a subexpression of another.+--+-- > > (xx -+- yy) `isSubexprOf` (zz -+- (xx -+- yy))+-- > True+--+-- > > (xx -+- yy) `isSubexprOf` abs' (yy -+- xx)+-- > False+--+-- > > xx `isSubexprOf` yy+-- > False+isSubexprOf :: Expr -> Expr -> Bool+isSubexprOf e = (e `elem`) . subexprs
+ src/Data/Express/Name.hs view
@@ -0,0 +1,248 @@+-- |+-- Module : Data.Express.Name+-- Copyright : (c) 2019 Rudy Matela+-- License : 3-Clause BSD (see the file LICENSE)+-- Maintainer : Rudy Matela <rudy@matela.com.br>+--+-- Defines the 'Name' type class.+module Data.Express.Name+ ( Name (..)+ , names+ , variableNamesFromTemplate+ )+where++import Data.Express.Utils.String++import Data.Char+import Data.List+import Data.Ratio (Ratio)+import Data.Word (Word) -- for GHC <= 7.8++-- |+-- If we were to come up with a variable name for the given type+-- what 'name' 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':+--+-- > > 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''", ...]+class Name a where+ -- | /O(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"+ name :: a -> String+ name _ = "x"++-- |+-- > name (undefined :: ()) = "u"+-- > names (undefined :: ()) = ["u", "v", "w", "u'", "v'", ...]+instance Name () where name _ = "u"++-- |+-- > name (undefined :: Bool) = "p"+-- > names (undefined :: Bool) = ["p", "q", "r", "p'", "q'", ...]+instance Name Bool where name _ = "p"++-- |+-- > name (undefined :: Int) = "x"+-- > names (undefined :: Int) = ["x", "y", "z", "x'", "y'", ...]+instance Name Int where name _ = "x"++-- |+-- > name (undefined :: Integer) = "x"+-- > names (undefined :: Integer) = ["x", "y", "z", "x'", ...]+instance Name Integer where name _ = "x"++-- |+-- > name (undefined :: Char) = "c"+-- > names (undefined :: Char) = ["c", "d", "e", "c'", "d'", ...]+instance Name Char where name _ = "c"++-- |+-- > name (undefined :: Ordering) = "o"+-- > names (undefined :: Ordering) = ["o", "p", "q", "o'", ...]+instance Name Ordering where name _ = "o"++-- |+-- > name (undefined :: Rational) = "q"+-- > names (undefined :: Rational) = ["q", "r", "s", "q'", ...]+instance Name (Ratio a) where name _ = "q"++-- |+-- > name (undefined :: Float) = "x"+-- > names (undefined :: Float) = ["x", "y", "z", "x'", ...]+instance Name Float where name _ = "x"++-- |+-- > name (undefined :: Double) = "x"+-- > names (undefined :: Double) = ["x", "y", "z", "x'", ...]+instance Name Double where name _ = "x"++-- |+-- > names (undefined :: ()->()) = ["f", "g", "h", "f'", ...]+-- > names (undefined :: Int->Int) = ["f", "g", "h", ...]+instance Name (a -> b) where name _ = "f"++-- |+-- > names (undefined :: Maybe Int) = ["mx", "mx1", "mx2", ...]+-- > nemes (undefined :: Maybe Bool) = ["mp", "mp1", "mp2", ...]+instance Name a => Name (Maybe a) where+ name mx = "m" ++ name x+ where+ Just x = mx++-- |+-- > names (undefined :: Either Int Int) = ["exy", "exy1", ...]+-- > names (undefined :: Either Int Bool) = ["exp", "exp1", ...]+instance (Name a, Name b) => Name (Either a b) where+ name exy = "e" ++ n ++ m+ where+ Left x = exy+ Right y = exy+ n = name x+ m = head $ names y \\ [n]++-- |+-- > names (undefined :: (Int,Int)) = ["xy", "zw", "xy'", ...]+-- > names (undefined :: (Bool,Bool)) = ["pq", "rs", "pq'", ...]+instance (Name a, Name b) => Name (a,b) where+ name xy = n ++ m+ where+ (x,y) = xy+ n = name x+ m = head $ names y \\ [n]++-- |+-- > names (undefined :: (Int,Int,Int)) = ["xyz","uvw", ...]+-- > names (undefined :: (Int,Bool,Char)) = ["xpc", "xpc1", ...]+instance (Name a, Name b, Name c) => Name (a,b,c) where+ name xyz = n ++ m ++ o+ where+ (x,y,z) = xyz+ n = name x+ m = head $ names y \\ [n]+ o = head $ names z \\ [n,m]++-- |+-- > names (undefined :: ((),(),(),())) = ["uuuu", "uuuu1", ...]+-- > names (undefined :: (Int,Int,Int,Int)) = ["xxxx", ...]+instance (Name a, Name b, Name c, Name d) => Name (a,b,c,d) where+ name xyzw = name x ++ name y ++ name z ++ name w where (x,y,z,w) = xyzw++-- |+-- > names (undefined :: [Int]) = ["xs", "ys", "zs", "xs'", ...]+-- > names (undefined :: [Bool]) = ["ps", "qs", "rs", "ps'", ...]+instance Name a => Name [a] where+ name xs = name (head xs) ++ "s"++-- |+-- Returns na infinite list of variable names from the given type:+-- the result of 'variableNamesFromTemplate' after 'name'.+--+-- > > 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''", ...]+names :: Name a => a -> [String]+names = variableNamesFromTemplate . name+++-- instances of further types and arities --++instance Name Word where name _ = "x"++instance (Name a, Name b, Name c, Name d, Name e) => Name (a,b,c,d,e) where+ name xyzwv = name x ++ name y ++ name z ++ name w ++ name v+ where (x,y,z,w,v) = xyzwv++instance (Name a, Name b, Name c, Name d, Name e, Name f)+ => Name (a,b,c,d,e,f) where+ name xyzwvu = name x ++ name y ++ name z ++ name w ++ name v ++ name u+ where (x,y,z,w,v,u) = xyzwvu++instance (Name a, Name b, Name c, Name d, Name e, Name f, Name g)+ => Name (a,b,c,d,e,f,g) where+ name xyzwvut = name x ++ name y ++ name z ++ name w+ ++ name v ++ name u ++ name t+ where (x,y,z,w,v,u,t) = xyzwvut++instance (Name a, Name b, Name c, Name d, Name e, Name f, Name g, Name h)+ => Name (a,b,c,d,e,f,g,h) where+ name xyzwvuts = name x ++ name y ++ name z ++ name w+ ++ name v ++ name u ++ name t ++ name s+ where (x,y,z,w,v,u,t,s) = xyzwvuts++instance ( Name a, Name b, Name c, Name d+ , Name e, Name f, Name g, Name h+ , Name i)+ => Name (a,b,c,d,e,f,g,h,i) where+ name xyzwvutsr = name x ++ name y ++ name z ++ name w+ ++ name v ++ name u ++ name t ++ name s+ ++ name r+ where (x,y,z,w,v,u,t,s,r) = xyzwvutsr++instance ( Name a, Name b, Name c, Name d+ , Name e, Name f, Name g, Name h+ , Name i, Name j )+ => Name (a,b,c,d,e,f,g,h,i,j) where+ name xyzwvutsrq = name x ++ name y ++ name z ++ name w+ ++ name v ++ name u ++ name t ++ name s+ ++ name r ++ name q+ where (x,y,z,w,v,u,t,s,r,q) = xyzwvutsrq++instance ( Name a, Name b, Name c, Name d+ , Name e, Name f, Name g, Name h+ , Name i, Name j, Name k )+ => Name (a,b,c,d,e,f,g,h,i,j,k) where+ name xyzwvutsrqp = name x ++ name y ++ name z ++ name w+ ++ name v ++ name u ++ name t ++ name s+ ++ name r ++ name q ++ name p+ where (x,y,z,w,v,u,t,s,r,q,p) = xyzwvutsrqp++instance ( Name a, Name b, Name c, Name d+ , Name e, Name f, Name g, Name h+ , Name i, Name j, Name k, Name l )+ => Name (a,b,c,d,e,f,g,h,i,j,k,l) where+ name xyzwvutsrqpo = name x ++ name y ++ name z ++ name w+ ++ name v ++ name u ++ name t ++ name s+ ++ name r ++ name q ++ name p ++ name o+ where (x,y,z,w,v,u,t,s,r,q,p,o) = xyzwvutsrqpo
+ src/Data/Express/Name/Derive.hs view
@@ -0,0 +1,54 @@+{-# LANGUAGE TemplateHaskell, CPP #-}+-- |+-- Module : Data.Express.Name.Derive+-- Copyright : (c) 2019 Rudy Matela+-- License : 3-Clause BSD (see the file LICENSE)+-- Maintainer : Rudy Matela <rudy@matela.com.br>+--+-- Allows automatic derivation of 'Name' typeclass instances.+module Data.Express.Name.Derive+ ( deriveName+ , deriveNameCascading+ , deriveNameIfNeeded+ )+where++import qualified Data.Express.Name as N++import Control.Monad+import Data.Char+import Data.List+import Data.Express.Utils.TH++-- | Derives a 'N.Name' instance+-- for the given type 'Name'.+--+-- This function needs the @TemplateHaskell@ extension.+deriveName :: Name -> DecsQ+deriveName = deriveWhenNeededOrWarn ''N.Name reallyDeriveName++-- | Same as 'deriveName' but does not warn when instance already exists+-- ('deriveName' is preferable).+deriveNameIfNeeded :: Name -> DecsQ+deriveNameIfNeeded = deriveWhenNeeded ''N.Name reallyDeriveName++-- | Derives a 'N.Name' instance for a given type 'Name'+-- cascading derivation of type arguments as well.+deriveNameCascading :: Name -> DecsQ+deriveNameCascading = deriveWhenNeeded ''N.Name reallyDeriveNameCascading++reallyDeriveName :: Name -> DecsQ+reallyDeriveName t = do+ (nt,vs) <- normalizeType t+ [d| instance N.Name $(return nt) where+ name _ = $(stringE vname) |]+ where+ showJustName = reverse . takeWhile (/= '.') . reverse . show+ vname = map toLower . take 1 $ showJustName t+-- TODO: on deriveName, use full camelCase name?+-- TODO: on deriveName, use x for Num instances?++-- Not only really derive Name instances,+-- but cascade through argument types.+reallyDeriveNameCascading :: Name -> DecsQ+reallyDeriveNameCascading = reallyDeriveCascading ''N.Name reallyDeriveName
+ src/Data/Express/Utils/List.hs view
@@ -0,0 +1,105 @@+-- |+-- Module : Data.Express.Utils.List+-- Copyright : (c) 2019 Rudy Matela+-- License : 3-Clause BSD (see the file LICENSE)+-- Maintainer : Rudy Matela <rudy@matela.com.br>+--+-- Re-exports the "Data.List" module along with additional functions over+-- lists.+{-# LANGUAGE CPP #-}+module Data.Express.Utils.List+ ( nubSort+ , isPermutationOf+ , isSubsetOf+ , isNub+ , lookupId+ , (+++)+ , module Data.List+#if __GLASGOW_HASKELL__ < 710+ , isSubsequenceOf+#endif+ )+where++import Data.Function (on)+import Data.List+import Data.Maybe (fromMaybe)++-- | /O(n log n)/.+-- 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]+nubSort :: Ord a => [a] -> [a]+nubSort = nnub . sort+ where+ -- linear nub of adjacent values+ nnub [] = []+ nnub [x] = [x]+ nnub (x:xs) = x : nnub (dropWhile (==x) xs)++-- | /O(n log n)/.+-- Checks that all elements of the first list are elements of the second.+isSubsetOf :: Ord a => [a] -> [a] -> Bool+xs `isSubsetOf` ys = nubSort xs `isSubsequenceOf` nubSort ys+++#if __GLASGOW_HASKELL__ < 710+-- only exported from Data.List since base 4.8.0.0+isSubsequenceOf :: Eq a => [a] -> [a] -> Bool+isSubsequenceOf [] _ = True+isSubsequenceOf (_:_) [] = False+isSubsequenceOf (x:xs) (y:ys) | x == y = xs `isSubsequenceOf` ys+ | otherwise = (x:xs) `isSubsequenceOf` ys+#endif++-- | /O(n log n)/.+-- Checks that all elements of the first list are elements of the second.+isPermutationOf :: Ord a => [a] -> [a] -> Bool+isPermutationOf = (==) `on` sort++-- | /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] = False+isNub :: Ord a => [a] -> Bool+isNub xs = length (nubSort xs) == length xs++-- | /O(n)/.+-- Like 'lookup' but returns the key itself if nothing is found.+--+-- > > lookupId 5 [(1,2),(3,4)]+-- > 5+--+-- > > lookupId 5 [(1,2),(3,4),(5,6)]+-- > 6+lookupId :: Eq a => a -> [(a,a)] -> a+lookupId x = fromMaybe x . lookup x++(+++) :: Ord a => [a] -> [a] -> [a]+(+++) = nubMerge+infixr 5 +++++nubMergeBy :: (a -> a -> Ordering) -> [a] -> [a] -> [a]+nubMergeBy cmp (x:xs) (y:ys) = case x `cmp` y of+ LT -> x:nubMergeBy cmp xs (y:ys)+ GT -> y:nubMergeBy cmp (x:xs) ys+ EQ -> x:nubMergeBy cmp xs ys+nubMergeBy _ xs ys = xs ++ ys++nubMerge :: Ord a => [a] -> [a] -> [a]+nubMerge = nubMergeBy compare
+ src/Data/Express/Utils/String.hs view
@@ -0,0 +1,171 @@+-- |+-- Module : Data.Express.Utils.String+-- Copyright : (c) 2016-2019 Rudy Matela+-- License : 3-Clause BSD (see the file LICENSE)+-- Maintainer : Rudy Matela <rudy@matela.com.br>+--+-- Utilities for manipulating strings.+--+-- At some point, this file was part of the Speculate tool.+module Data.Express.Utils.String+ ( module Data.String+ , module Data.Char+ , unquote+ , atomic+ , outernmostPrec+ , isNegativeLiteral+ , isInfix, isPrefix, isInfixedPrefix+ , toPrefix+ , prec+ , variableNamesFromTemplate+ , primeCycle+ )+where++import Data.String+import Data.Char+import Data.Functor ((<$>)) -- for GHC < 7.10++-- | Unquotes a string if possible, otherwise, this is just an identity.+--+-- > > unquote "\"string\""+-- > "string"+-- > > unquote "something else"+-- > "something else"+unquote :: String -> String+unquote ('"':s) | last s == '"' = init s+unquote s = s++-- | Checks 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]"+-- > True+--+-- but this does not cause problems for (all?) most cases.+atomic :: String -> Bool+atomic s | all (not . isSpace) s = True+atomic ('\'':s) | last s == '\'' = True+atomic ('"':s) | last s == '"' = True+atomic ('[':s) | last s == ']' = True+atomic ('(':s) | last s == ')' = True+atomic _ = False++outernmostPrec :: String -> Maybe Int+outernmostPrec s =+ case words s of+ [l,o,r] | isInfix o -> Just (prec o)+ _ -> Nothing++isNegativeLiteral :: String -> Bool+isNegativeLiteral s | not (atomic s) = False+isNegativeLiteral "-" = False+isNegativeLiteral ('-':cs) = all isDigit cs+isNegativeLiteral _ = False++-- | Check if a function / operator is infix+--+-- > isInfix "foo" == False+-- > isInfix "(+)" == False+-- > isInfix "`foo`" == True+-- > isInfix "+" == True+isInfix :: String -> Bool+isInfix (c:_) = c `notElem` "()'\"[_" && not (isAlphaNum c)+isInfix "" = error "isInfix: empty string"++-- | Returns the precedence of default Haskell operators+prec :: String -> Int+prec " " = 10+prec "!!" = 9+prec "." = 9+prec "^" = 8+prec "^^" = 8+prec "**" = 8+prec "*" = 7+prec "/" = 7+prec "%" = 7+prec "+" = 6+prec "-" = 6+prec ":" = 5+prec "++" = 5+prec "\\" = 5+prec ">" = 4+prec "<" = 4+prec ">=" = 4+prec "<=" = 4+prec "==" = 4+prec "/=" = 4+prec "`elem`" = 4+prec "&&" = 3+prec "||" = 2+prec ">>=" = 1+prec ">>" = 1+prec ">=>" = 1+prec "<=<" = 1+prec "$" = 0+prec "`seq`" = 0+prec "==>" = 0+prec "<==>" = 0+prec _ = 9++isPrefix :: String -> Bool+isPrefix = not . isInfix++-- | Is the string of the form @\`string\`@+isInfixedPrefix :: String -> Bool+isInfixedPrefix s | not (atomic s) = False+isInfixedPrefix ('`':cs) = last cs == '`'+isInfixedPrefix _ = False++-- | Transform an infix operator into an infix function:+--+-- > toPrefix "`foo`" == "foo"+-- > toPrefix "+" == "(+)"+toPrefix :: String -> String+toPrefix ('`':cs) = init cs+toPrefix cs = '(':cs ++ ")"++primeCycle :: [String] -> [String]+primeCycle [] = []+primeCycle ss = ss ++ map (++ "'") (primeCycle ss)++-- |+-- Returns 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''", ...]+variableNamesFromTemplate :: String -> [String]+variableNamesFromTemplate = primeCycle . f+ where+ f "" = f "x"+ f "x" = ["x", "y", "z"] -- redundant, for clarity+ f "xy" = ["xy", "zw"]+ f "xyz" = ["xyz", "uvw"]+ f cs | isDigit (last cs) = map (\n -> init cs ++ show n) [digitToInt (last cs)..]+ f [c] | c `elem` ['a'..'x'] = let x = ord c in map ((:[]) . chr) [x,x+1,x+2]+ f cs | last cs == 's' = (++ "s") <$> f (init cs)+ f [c,d] | ord d - ord c == 1 = [[c,d], [chr $ ord c + 2, chr $ ord d + 2]]+ f cs | cs == "y" || cs == "z" = cs : map (\n -> cs ++ show n) [1..]+ f cs = [cs]
+ src/Data/Express/Utils/TH.hs view
@@ -0,0 +1,290 @@+{-# LANGUAGE TemplateHaskell, CPP #-}+-- |+-- Module : Data.Express.Name.Derive+-- Copyright : (c) 2019 Rudy Matela+-- License : 3-Clause BSD (see the file LICENSE)+-- Maintainer : Rudy Matela <rudy@matela.com.br>+--+-- Template Haskell utilities.+module Data.Express.Utils.TH+ ( reallyDeriveCascading+ , deriveWhenNeeded+ , deriveWhenNeededOrWarn+ , typeConArgs+ , typeConArgsThat+ , typeConCascadingArgsThat+ , normalizeType+ , normalizeTypeUnits+ , isInstanceOf+ , isntInstanceOf+ , typeArity+ , typeConstructors+ , isTypeSynonym+ , typeSynonymType+ , mergeIFns+ , mergeI+ , lookupValN+ , showJustName+ , typeConstructorsArgNames+ , (|=>|)+ , whereI+ , module Language.Haskell.TH+ )+where++import Control.Monad+import Data.List+import Language.Haskell.TH++deriveWhenNeeded :: Name -> (Name -> DecsQ) -> Name -> DecsQ+deriveWhenNeeded = deriveWhenNeededX False++deriveWhenNeededOrWarn :: Name -> (Name -> DecsQ) -> Name -> DecsQ+deriveWhenNeededOrWarn = deriveWhenNeededX True++deriveWhenNeededX :: Bool -> Name -> (Name -> DecsQ) -> Name -> DecsQ+deriveWhenNeededX warnExisting cls reallyDerive t = do+ is <- t `isInstanceOf` cls+ if is+ then do+ unless (not warnExisting)+ (reportWarning $ "Instance " ++ showJustName cls ++ " " ++ showJustName t+ ++ " already exists, skipping derivation")+ return []+ else+ reallyDerive t++showJustName :: Name -> String+showJustName = reverse . takeWhile (/= '.') . reverse . show++reallyDeriveCascading :: Name -> (Name -> DecsQ) -> Name -> DecsQ+reallyDeriveCascading cls reallyDerive t =+ return . concat+ =<< mapM reallyDerive+ =<< filterM (liftM not . isTypeSynonym)+ =<< return . (t:) . delete t+ =<< t `typeConCascadingArgsThat` (`isntInstanceOf` cls)++typeConArgs :: Name -> Q [Name]+typeConArgs t = do+ is <- isTypeSynonym t+ if is+ then liftM typeConTs $ typeSynonymType t+ else liftM (nubMerges . map typeConTs . concat . map snd) $ typeConstructors t+ where+ typeConTs :: Type -> [Name]+ typeConTs (AppT t1 t2) = typeConTs t1 `nubMerge` typeConTs t2+ typeConTs (SigT t _) = typeConTs t+ typeConTs (VarT _) = []+ typeConTs (ConT n) = [n]+#if __GLASGOW_HASKELL__ >= 800+ -- typeConTs (PromotedT n) = [n] ?+ typeConTs (InfixT t1 n t2) = typeConTs t1 `nubMerge` typeConTs t2+ typeConTs (UInfixT t1 n t2) = typeConTs t1 `nubMerge` typeConTs t2+ typeConTs (ParensT t) = typeConTs t+#endif+ typeConTs _ = []++typeConArgsThat :: Name -> (Name -> Q Bool) -> Q [Name]+typeConArgsThat t p = do+ targs <- typeConArgs t+ tbs <- mapM (\t' -> do is <- p t'; return (t',is)) targs+ return [t' | (t',p) <- tbs, p]++typeConCascadingArgsThat :: Name -> (Name -> Q Bool) -> Q [Name]+t `typeConCascadingArgsThat` p = do+ ts <- t `typeConArgsThat` p+ let p' t' = do is <- p t'; return $ t' `notElem` (t:ts) && is+ tss <- mapM (`typeConCascadingArgsThat` p') ts+ return $ nubMerges (ts:tss)++-- Normalizes a type by applying it to necessary type variables, making it+-- accept "zero" parameters. The normalized type is tupled with a list of+-- necessary type variables.+--+-- Suppose:+--+-- > data DT a b c ... = ...+--+-- Then, in pseudo-TH:+--+-- > normalizeType [t|DT|] == Q (DT a b c ..., [a, b, c, ...])+normalizeType :: Name -> Q (Type, [Type])+normalizeType t = do+ ar <- typeArity t+ vs <- newVarTs ar+ return (foldl AppT (ConT t) vs, vs)+ where+ newNames :: [String] -> Q [Name]+ newNames = mapM newName+ newVarTs :: Int -> Q [Type]+ newVarTs n = liftM (map VarT)+ $ newNames (take n . map (:[]) $ cycle ['a'..'z'])++-- Normalizes a type by applying it to units (`()`) while possible.+--+-- > normalizeTypeUnits ''Int === [t| Int |]+-- > normalizeTypeUnits ''Maybe === [t| Maybe () |]+-- > normalizeTypeUnits ''Either === [t| Either () () |]+normalizeTypeUnits :: Name -> Q Type+normalizeTypeUnits t = do+ ar <- typeArity t+ return (foldl AppT (ConT t) (replicate ar (TupleT 0)))++-- Given a type name and a class name,+-- returns whether the type is an instance of that class.+isInstanceOf :: Name -> Name -> Q Bool+isInstanceOf tn cl = do+ ty <- normalizeTypeUnits tn+ isInstance cl [ty]++isntInstanceOf :: Name -> Name -> Q Bool+isntInstanceOf tn cl = liftM not (isInstanceOf tn cl)++-- | Given 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 1+--+-- This works for Data's and Newtype's and it is useful when generating+-- typeclass instances.+typeArity :: Name -> Q Int+typeArity t = do+ ti <- reify t+ return . length $ case ti of+#if __GLASGOW_HASKELL__ < 800+ TyConI (DataD _ _ ks _ _) -> ks+ TyConI (NewtypeD _ _ ks _ _) -> ks+#else+ TyConI (DataD _ _ ks _ _ _) -> ks+ TyConI (NewtypeD _ _ ks _ _ _) -> ks+#endif+ TyConI (TySynD _ ks _) -> ks+ _ -> error $ "error (typeArity): symbol " ++ show t+ ++ " is not a newtype, data or type synonym"++-- Given a type name, returns a list of its type constructor names paired with+-- the type arguments they take.+--+-- > typeConstructors ''() === Q [('(),[])]+--+-- > typeConstructors ''(,) === Q [('(,),[VarT a, VarT b])]+--+-- > typeConstructors ''[] === Q [('[],[]),('(:),[VarT a,AppT ListT (VarT a)])]+--+-- > data Pair a = P a a+-- > typeConstructors ''Pair === Q [('P,[VarT a, VarT a])]+--+-- > data Point = Pt Int Int+-- > typeConstructors ''Point === Q [('Pt,[ConT Int, ConT Int])]+typeConstructors :: Name -> Q [(Name,[Type])]+typeConstructors t = do+ ti <- reify t+ return . map simplify $ case ti of+#if __GLASGOW_HASKELL__ < 800+ TyConI (DataD _ _ _ cs _) -> cs+ TyConI (NewtypeD _ _ _ c _) -> [c]+#else+ TyConI (DataD _ _ _ _ cs _) -> cs+ TyConI (NewtypeD _ _ _ _ c _) -> [c]+#endif+ _ -> error $ "error (typeConstructors): symbol " ++ show t+ ++ " is neither newtype nor data"+ where+ simplify (NormalC n ts) = (n,map snd ts)+ simplify (RecC n ts) = (n,map trd ts)+ simplify (InfixC t1 n t2) = (n,[snd t1,snd t2])+ trd (x,y,z) = z++isTypeSynonym :: Name -> Q Bool+isTypeSynonym t = do+ ti <- reify t+ return $ case ti of+ TyConI (TySynD _ _ _) -> True+ _ -> False++typeSynonymType :: Name -> Q Type+typeSynonymType t = do+ ti <- reify t+ return $ case ti of+ TyConI (TySynD _ _ t') -> t'+ _ -> error $ "error (typeSynonymType): symbol " ++ show t+ ++ " is not a type synonym"++-- Append to instance contexts in a declaration.+--+-- > sequence [[|Eq b|],[|Eq c|]] |=>| [t|instance Eq a => Cl (Ty a) where f=g|]+-- > == [t| instance (Eq a, Eq b, Eq c) => Cl (Ty a) where f = g |]+(|=>|) :: Cxt -> DecsQ -> DecsQ+c |=>| qds = do ds <- qds+ return $ map (`ac` c) ds+#if __GLASGOW_HASKELL__ < 800+ where ac (InstanceD c ts ds) c' = InstanceD (c++c') ts ds+ ac d _ = d+#else+ where ac (InstanceD o c ts ds) c' = InstanceD o (c++c') ts ds+ ac d _ = d+#endif++mergeIFns :: DecsQ -> DecsQ+mergeIFns qds = do ds <- qds+ return $ map m' ds+ where+#if __GLASGOW_HASKELL__ < 800+ m' (InstanceD c ts ds) = InstanceD c ts [foldr1 m ds]+#else+ m' (InstanceD o c ts ds) = InstanceD o c ts [foldr1 m ds]+#endif+ FunD n cs1 `m` FunD _ cs2 = FunD n (cs1 ++ cs2)++mergeI :: DecsQ -> DecsQ -> DecsQ+qds1 `mergeI` qds2 = do ds1 <- qds1+ ds2 <- qds2+ return $ ds1 `m` ds2+ where+#if __GLASGOW_HASKELL__ < 800+ [InstanceD c ts ds1] `m` [InstanceD _ _ ds2] = [InstanceD c ts (ds1 ++ ds2)]+#else+ [InstanceD o c ts ds1] `m` [InstanceD _ _ _ ds2] = [InstanceD o c ts (ds1 ++ ds2)]+#endif++whereI :: DecsQ -> [Dec] -> DecsQ+qds `whereI` w = do ds <- qds+ return $ map (`aw` w) ds+#if __GLASGOW_HASKELL__ < 800+ where aw (InstanceD c ts ds) w' = InstanceD c ts (ds++w')+ aw d _ = d+#else+ where aw (InstanceD o c ts ds) w' = InstanceD o c ts (ds++w')+ aw d _ = d+#endif++-- > nubMerge xs ys == nub (merge xs ys)+-- > nubMerge xs ys == nub (sort (xs ++ ys))+nubMerge :: Ord a => [a] -> [a] -> [a]+nubMerge [] ys = ys+nubMerge xs [] = xs+nubMerge (x:xs) (y:ys) | x < y = x : xs `nubMerge` (y:ys)+ | x > y = y : (x:xs) `nubMerge` ys+ | otherwise = x : xs `nubMerge` ys++nubMerges :: Ord a => [[a]] -> [a]+nubMerges = foldr nubMerge []++typeConstructorsArgNames :: Name -> Q [(Name,[Name])]+typeConstructorsArgNames t = do+ cs <- typeConstructors t+ sequence [ do ns <- sequence [newName "x" | _ <- ts]+ return (c,ns)+ | (c,ts) <- cs ]++lookupValN :: String -> Q Name+lookupValN s = do+ mn <- lookupValueName s+ case mn of+ Just n -> return n+ Nothing -> fail $ "lookupValN: cannot find " ++ s
+ src/Data/Express/Utils/Typeable.hs view
@@ -0,0 +1,121 @@+-- |+-- Module : Data.Express.Utils.Typeable+-- Copyright : (c) 2016-2019 Rudy Matela+-- License : 3-Clause BSD (see the file LICENSE)+-- Maintainer : Rudy Matela <rudy@matela.com.br>+--+-- This module is part of Express.+--+-- Utilities to manipulate 'TypeRep's (of 'Typeable' values).+module Data.Express.Utils.Typeable+ ( tyArity+ , unFunTy+ , isFunTy+ , argumentTy+ , resultTy+ , finalResultTy+ , boolTy+ , intTy+ , orderingTy+ , mkComparisonTy+ , mkCompareTy+ , funTyCon+ , compareTy+ , elementTy+ , (->::)+ , module Data.Typeable+ )+where++import Data.Typeable+import Data.Monoid ((<>))++-- Different versions of Typeable/GHC provide different orderings for TypeReps.+-- The following is a version independent ordering, with the following+-- properties:+--+-- * functional types with more arguments are larger;+-- * type constructors with more arguments are larger.+compareTy :: TypeRep -> TypeRep -> Ordering+compareTy t1 t2 | t1 == t2 = EQ -- optional optimization+compareTy t1 t2 = tyArity t1 `compare` tyArity t2+ <> length ts1 `compare` length ts2+ <> show c1 `compare` show c2+ <> foldr (<>) EQ (zipWith compareTy ts1 ts2)+ where+ (c1,ts1) = splitTyConApp t1+ (c2,ts2) = splitTyConApp t2++tyArity :: TypeRep -> Int+tyArity t+ | isFunTy t = 1 + tyArity (resultTy t)+ | otherwise = 0++finalResultTy :: TypeRep -> TypeRep+finalResultTy t+ | isFunTy t = finalResultTy (resultTy t)+ | otherwise = t++unFunTy :: TypeRep -> (TypeRep,TypeRep)+unFunTy t+ | isFunTy t = let (f,[a,b]) = splitTyConApp t in (a,b)+ | otherwise = error $ "error (unFunTy): `" ++ show t ++ "` is not a function type"++argumentTy :: TypeRep -> TypeRep+argumentTy = fst . unFunTy++resultTy :: TypeRep -> TypeRep+resultTy = snd . unFunTy++-- | This 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 type+elementTy :: TypeRep -> TypeRep+elementTy t+ | isListTy t = let (_,[a]) = splitTyConApp t in a+ | otherwise = error $ "error (elementTy): `" ++ show t ++ "' is not a list type"++boolTy :: TypeRep+boolTy = typeOf (undefined :: Bool)++intTy :: TypeRep+intTy = typeOf (undefined :: Int)++orderingTy :: TypeRep+orderingTy = typeOf (undefined :: Ordering)++funTyCon :: TyCon+funTyCon = typeRepTyCon $ typeOf (undefined :: () -> ())++listTyCon :: TyCon+listTyCon = typeRepTyCon $ typeOf (undefined :: [()])++isFunTy :: TypeRep -> Bool+isFunTy t =+ case splitTyConApp t of+ (con,[_,_]) | con == funTyCon -> True+ _ -> False++isListTy :: TypeRep -> Bool+isListTy t = case splitTyConApp t of+ (con,[_]) | con == listTyCon -> True+ _ -> False++mkComparisonTy :: TypeRep -> TypeRep+mkComparisonTy a = a ->:: a ->:: boolTy++mkCompareTy :: TypeRep -> TypeRep+mkCompareTy a = a ->:: a ->:: orderingTy++-- | An infix alias for 'mkFunTy'. It is right associative.+(->::) :: TypeRep -> TypeRep -> TypeRep+(->::) = mkFunTy+infixr 9 ->::
+ stack-lts-11.yaml view
@@ -0,0 +1,17 @@+# stack.yaml docs:+# https://docs.haskellstack.org/en/stable/yaml_configuration/++# resolver: nightly-2015-09-21+# resolver: ghc-7.10.2+resolver: lts-11.22++packages:+- .++extra-deps:+- leancheck-0.9.1+- speculate-0.3.5++flags: {}++extra-package-dbs: []
+ stack.yaml view
@@ -0,0 +1,15 @@+# stack.yaml docs:+# https://docs.haskellstack.org/en/stable/yaml_configuration/++# resolver: nightly-2015-09-21+# resolver: ghc-7.10.2+resolver: lts-13.6++packages:+- .++extra-deps: []++flags: {}++extra-package-dbs: []
+ test/Test.hs view
@@ -0,0 +1,77 @@+-- |+-- Module : Test+-- Copyright : (c) 2019 Rudy Matela+-- License : 3-Clause BSD (see the file LICENSE)+-- Maintainer : Rudy Matela <rudy@matela.com.br>+--+-- This module defines utilities used to test "Data.Express".+--+-- It should never be exported in @ express.cabal @.+module Test+ ( module Test.LeanCheck+ , module Test.LeanCheck.Utils+ , module Test.LeanCheck.Derive+ , module Data.Express.Fixtures+ , module Data.Express.Utils.List+ , module Data.Express.Utils.Typeable+ , module Test.ListableExpr+ , module Data.Maybe+ , module Data.Either+ , mainTest++ , tyBool+ , tyInt+ , tyChar+ , tyInts+ , tyIntToInt+ )+where++import System.Environment (getArgs)+import System.Exit (exitFailure)+import Data.List (elemIndices)+import Data.Typeable (TypeRep, typeOf)++import Data.Maybe+import Data.Either+import Test.LeanCheck+import Test.LeanCheck.Utils+import Test.LeanCheck.Derive+import Test.ListableExpr+import Data.Express.Fixtures+import Data.Express.Utils.List+import Data.Express.Utils.Typeable++reportTests :: [Bool] -> IO ()+reportTests tests =+ case elemIndices False tests of+ [] -> putStrLn "+++ Tests passed!"+ is -> do putStrLn ("*** Failed tests:" ++ show is)+ exitFailure++getMaxTestsFromArgs :: Int -> IO Int+getMaxTestsFromArgs n = do+ as <- getArgs+ return $ case as of+ (s:_) -> read s+ _ -> n++mainTest :: (Int -> [Bool]) -> Int -> IO ()+mainTest tests n' = do+ n <- getMaxTestsFromArgs n'+ reportTests (tests n)++tyBool :: TypeRep+tyBool = typeOf (undefined :: Bool)++tyInt :: TypeRep+tyInt = typeOf (undefined :: Int)++tyChar :: TypeRep+tyChar = typeOf (undefined :: Char)++tyInts :: TypeRep+tyInts = typeOf (undefined :: [Int])++tyIntToInt :: TypeRep+tyIntToInt = typeOf (undefined :: Int -> Int)
+ test/Test/ListableExpr.hs view
@@ -0,0 +1,285 @@+-- |+-- Module : Test.ListableExpr+-- Copyright : (c) 2019 Rudy Matela+-- License : 3-Clause BSD (see the file LICENSE)+-- Maintainer : Rudy Matela <rudy@matela.com.br>+--+-- This module exports a 'Listable' 'Expr' instance.+-- This instance does not, by any means, list all possible expressions.+-- It lists expressions based on a subset of the symbols exported by+-- "Data.Express.Fixtures".+--+-- This is only intended to be used for testing,+-- so this will not be exported on @ express.cabal @.+module Test.ListableExpr+ (+ -- * The Expr type+ Expr++ -- * Expressions of a type+ , IntE (..)+ , BoolE (..)+ , IntsE (..)+ , CharE (..)++ , IntE0 (..)+ , IntEV (..)+ , BoolE0 (..)+ , BoolEV (..)+ , IntsE0 (..)+ , IntsEV (..)+ , CharE0 (..)+ , CharEV (..)++ -- ** Functional values+ , IntToIntE (..)+ , IntToIntToIntE (..)+ , BoolToBoolE (..)+ , BoolToBoolToBoolE (..)++ , SameTypeE (..)+ , unSameTypeE+ , SameTypedPairsE (..)++ -- * Terminal expressions+ , E0 (..)+ , EV (..)++ -- * Ill typed expressions+ , Ill (..)+ )+where++-- TODO: StringE++import Test.LeanCheck+import Test.LeanCheck.Function.ShowFunction+import Data.Express.Fixtures+import Data.Function (on)++-- | Terminal constants.+newtype E0 = E0 { unE0 :: Expr }++-- | Variables.+newtype EV = EV { unEV :: Expr }++-- | Expression of 'Int' type.+newtype IntE = IntE { unIntE :: Expr }++-- | Constant terminal value of 'Int' type.+newtype IntE0 = IntE0 { unIntE0 :: Expr }++-- | Varialbe of 'Int' type.+newtype IntEV = IntEV { unIntEV :: Expr }++-- | Functions from Int to Int+newtype IntToIntE = IntToIntE { unIntToIntE :: Expr }+newtype IntToIntToIntE = IntToIntToIntE { unIntToIntToIntE :: Expr }++-- | Expression of 'Bool' type.+newtype BoolE = BoolE { unBoolE :: Expr }++-- | Constant terminal value of 'Bool' type.+newtype BoolE0 = BoolE0 { unBoolE0 :: Expr }++-- | Varialbe of 'Bool' type.+newtype BoolEV = BoolEV { unBoolEV :: Expr }++-- | Functions from Bool to Bool+newtype BoolToBoolE = BoolToBoolE { unBoolToBoolE :: Expr }+newtype BoolToBoolToBoolE = BoolToBoolToBoolE { unBoolToBoolToBoolE :: Expr }++newtype CharE = CharE { unCharE :: Expr }++newtype CharE0 = CharE0 { unCharE0 :: Expr }++newtype CharEV = CharEV { unCharEV :: Expr }++data SameTypeE = SameTypeE Expr Expr++unSameTypeE :: SameTypeE -> (Expr,Expr)+unSameTypeE (SameTypeE e1 e2) = (e1,e2)++data SameTypedPairsE = SameTypedPairsE { unSameTypedPairsE :: [(Expr,Expr)] }++-- | Ill typed expressions.+newtype Ill = Ill { unIll :: Expr }+++instance Show E0 where show (E0 e) = show e+instance Show EV where show (EV e) = show e++instance Show IntE where show (IntE e) = show e++instance Show IntE0 where show (IntE0 e) = show e+instance Show IntEV where show (IntEV e) = show e++instance Show IntToIntE where show (IntToIntE e) = show e+instance Show IntToIntToIntE where show (IntToIntToIntE e) = show e++instance Show BoolE where show (BoolE e) = show e++instance Show BoolE0 where show (BoolE0 e) = show e+instance Show BoolEV where show (BoolEV e) = show e++instance Show BoolToBoolE where show (BoolToBoolE e) = show e+instance Show BoolToBoolToBoolE where show (BoolToBoolToBoolE e) = show e++instance Show IntsE where show (IntsE e) = show e++instance Show IntsE0 where show (IntsE0 e) = show e+instance Show IntsEV where show (IntsEV e) = show e++instance Show CharE where show (CharE e) = show e++instance Show CharE0 where show (CharE0 e) = show e+instance Show CharEV where show (CharEV e) = show e++instance Show SameTypeE where show (SameTypeE e1 e2) = show (e1,e2)++instance Show SameTypedPairsE where show (SameTypedPairsE ees) = show ees++-- | Expression of 'Ints' type.+newtype IntsE = IntsE { unIntsE :: Expr }++-- | Constant terminal value of 'Ints' type.+newtype IntsE0 = IntsE0 { unIntsE0 :: Expr }++-- | Varialbe of 'Ints' type.+newtype IntsEV = IntsEV { unIntsEV :: Expr }++instance Show Ill where show (Ill e) = show e++instance Listable IntE where+ tiers = mapT IntE+ $ cons0 i_+ \/ cons1 unIntEV+ \/ cons1 unIntE0+ \/ cons2 (\(IntToIntE f) (IntE xx) -> f :$ xx)+ \/ cons1 (head' . unIntsE) `ofWeight` 2+ \/ cons1 (ord' . unCharE) `ofWeight` 2++instance Listable IntE0 where+ tiers = (IntE0 . val) `mapT` (tiers :: [[Int]])++instance Listable IntEV where+ list = map IntEV $ listVars "x" (undefined :: Int)++instance Listable IntToIntE where+ tiers = mapT IntToIntE+ $ cons0 idE+ \/ cons0 negateE `addWeight` 1+ \/ cons0 absE `addWeight` 1+ \/ cons2 (\(IntToIntToIntE ef) (IntE ex) -> ef :$ ex)+ \/ toTiers (listVars "f" (undefined :: Int -> Int)) `addWeight` 2++instance Listable IntToIntToIntE where+ list = map IntToIntToIntE [plus, times]++instance Listable IntsE where+ tiers = mapT IntsE+ $ cons0 is_+ \/ cons1 unIntsEV+ \/ cons1 unIntsE0+ \/ cons2 (\(IntE ex) (IntsE exs) -> ex -:- exs)+ \/ cons1 (tail' . unIntsE) `ofWeight` 2+ \/ cons2 (\(IntsE exs) (IntsE eys) -> exs -++- eys) `ofWeight` 2+ \/ cons1 (\(IntsE exs) -> sort' exs) `ofWeight` 3+ \/ cons2 (\(IntE ex) (IntsE exs) -> insert' ex exs) `ofWeight` 3++instance Listable IntsE0 where+ tiers = (IntsE0 . val) `mapT` (tiers :: [[ [Int] ]])++instance Listable IntsEV where+ list = map IntsEV $ listVars "xs" (undefined :: [Int])++instance Listable BoolE where+ tiers = mapT BoolE+ $ cons0 b_+ \/ cons1 unBoolEV+ \/ cons1 unBoolE0+ \/ cons2 (\(BoolToBoolE ef) (BoolE ep) -> ef :$ ep)+ \/ cons2 ((-==-) `on` unIntE) `addWeight` 2+ \/ cons2 ((-==-) `on` unBoolE) `addWeight` 2+ \/ cons2 ((-<=-) `on` unIntE) `addWeight` 3+ \/ cons2 ((-<=-) `on` unBoolE) `addWeight` 3+ \/ cons2 ((-<-) `on` unIntE) `addWeight` 4+ \/ cons2 ((-<-) `on` unBoolE) `addWeight` 4+ \/ cons2 ((-/=-) `on` unIntE) `addWeight` 5+ \/ cons2 ((-/=-) `on` unBoolE) `addWeight` 5+ \/ cons1 (odd' . unIntE) `addWeight` 2+ \/ cons1 (even' . unIntE) `addWeight` 2+ \/ cons2 (\(IntE ex) (IntsE exs) -> elem' ex exs) `addWeight` 2++instance Listable BoolE0 where+ tiers = (BoolE0 . val) `mapT` (tiers :: [[Bool]])++instance Listable BoolEV where+ list = map BoolEV $ listVars "p" (undefined :: Bool)++instance Listable BoolToBoolE where+ tiers = mapT BoolToBoolE+ $ cons0 notE+ \/ cons2 (\(BoolToBoolToBoolE ef) (BoolE ex) -> ef :$ ex)++instance Listable BoolToBoolToBoolE where+ list = map BoolToBoolToBoolE [orE, andE, implies]++instance Listable CharE where+ tiers = mapT CharE $ cons0 c_+ \/ cons1 unCharEV+ \/ cons1 unCharE0++instance Listable CharEV where+ list = map CharEV $ listVars "c" (undefined :: Char)++instance Listable CharE0 where+ tiers = (CharE0 . val) `mapT` (tiers :: [[Char]])++instance Listable SameTypeE where+ tiers = cons1 (\(IntE e1, IntE e2) -> SameTypeE e1 e2) `ofWeight` 0+ \/ cons1 (\(BoolE e1, BoolE e2) -> SameTypeE e1 e2) `ofWeight` 1+ \/ cons1 (\(IntsE e1, IntsE e2) -> SameTypeE e1 e2) `ofWeight` 1+ \/ cons1 (\(CharE e1, CharE e2) -> SameTypeE e1 e2) `ofWeight` 2+ \/ cons1 (\(IntToIntE e1, IntToIntE e2) -> SameTypeE e1 e2) `ofWeight` 2+ \/ cons1 (\(BoolToBoolE e1, BoolToBoolE e2) -> SameTypeE e1 e2) `ofWeight` 2+ \/ cons1 (\(BoolToBoolToBoolE e1, BoolToBoolToBoolE e2) -> SameTypeE e1 e2) `ofWeight` 2+ \/ cons1 (\(IntToIntToIntE e1, IntToIntToIntE e2) -> SameTypeE e1 e2) `ofWeight` 2++instance Listable SameTypedPairsE where+ tiers = cons1 (SameTypedPairsE . map unSameTypeE) `ofWeight` 0++instance Listable E0 where+ tiers = mapT E0+ $ cons1 unIntE0 `ofWeight` 0+ \/ cons1 unBoolE0 `ofWeight` 1+ \/ cons1 unIntsE0 `ofWeight` 1++instance Listable EV where+ tiers = mapT EV+ $ cons1 unIntEV `ofWeight` 0+ \/ cons1 unBoolEV `ofWeight` 1+ \/ cons1 unIntsEV `ofWeight` 1+++instance Listable Expr where+ tiers = reset (cons1 unIntE)+ \/ cons1 unBoolE+ \/ cons1 unCharE+ \/ cons1 unIntsE+ \/ cons1 unIntToIntE `addWeight` 1+ \/ cons1 unIntToIntToIntE `addWeight` 1+ \/ cons1 unBoolToBoolE `addWeight` 2+ \/ cons1 unBoolToBoolToBoolE `addWeight` 2+++-- | This listable instance only produces Ill typed expressions+instance Listable Ill where+ tiers = mapT Ill+ $ cons2 (\(IntE ef) (IntE ex) -> ef :$ ex) `ofWeight` 0+ \/ cons2 (\(IntToIntE ef) (IntToIntE ex) -> ef :$ ex)+ \/ cons2 (\(Ill ef) ex -> ef :$ ex)+ \/ cons2 (\ef (Ill ex)-> ef :$ ex)+++instance ShowFunction Expr where bindtiers = bindtiersShow
+ test/canon.hs view
@@ -0,0 +1,119 @@+-- Copyright (c) 2017-2018 Rudy Matela. -- Distributed under the 3-Clause BSD licence (see the file LICENSE).+import Test++main :: IO ()+main = mainTest tests 5040++tests :: Int -> [Bool]+tests n =+ [ True++ , canonicalize (xx -+- yy)+ == (xx -+- yy)+ , canonicalize (jj -+- (ii -+- ii))+ == (xx -+- (yy -+- yy))+ , canonicalize ((jj -+- ii) -+- (xx -+- xx))+ == ((xx -+- yy) -+- (zz -+- zz))++ -- these are just tests:+ -- canonicalizeWith expects the resulting list of the arg function to be infinite+ , canonicalizeWith (const ["i","j","k","l"]) (xx -+- yy)+ == (ii -+- jj)+ , canonicalizeWith (const ["i","j","k","l"]) (jj -+- (ii -+- ii))+ == (ii -+- (jj -+- jj))+ , canonicalizeWith (const ["i","j","k","l"]) ((jj -+- ii) -+- (xx -+- xx))+ == ((ii -+- jj) -+- (kk -+- kk))++ , canonicalize (xx -+- ord' cc) == (xx -+- ord' cc)+ , canonicalize (yy -+- ord' dd) == (xx -+- ord' cc)+ , canonicalize (ff xx -+- gg yy -+- ff yy) == (ff xx -+- gg yy -+- ff yy)+ , canonicalize (gg yy -+- ff xx -+- gg xx) == (ff xx -+- gg yy -+- ff yy)+ , canonicalizeWith (lookupNames $ reifyName (undefined :: Int -> Int -> Int) ++ preludeNameInstances)+ (zz -?- kk) == (var "f" (undefined :: Int -> Int -> Int) :$ xx :$ yy)++ -- canonicalizing holes --+ , canonicalize (hole (undefined :: Int )) == xx+ , canonicalize (hole (undefined :: Bool )) == pp+ , canonicalize (hole (undefined :: Char )) == cc+ , canonicalize (hole (undefined :: [Int] )) == xxs+ , canonicalize (hole (undefined :: [Char] )) == ccs+ , canonicalize (hole (undefined :: () )) == var "u" ()+ , canonicalize (hole (undefined :: Integer )) == var "x" (undefined :: Integer)+ , canonicalize (hole (undefined :: [Integer] )) == var "xs" (undefined :: [Integer])+ , canonicalize (hole (undefined :: Maybe Int )) == var "mx" (undefined :: Maybe Int)+ , canonicalize (hole (undefined :: (Int,Int) )) == var "xy" (undefined :: (Int,Int))++ , canonicalVariations (zero -+- xx) == [zero -+- xx]+ , canonicalVariations (zero -+- i_) == [zero -+- xx]+ , canonicalVariations (i_ -+- i_) == [xx -+- yy, xx -+- xx]+ , canonicalVariations (i_ -+- (i_ -+- ord' c_))+ == [ xx -+- (yy -+- ord' cc)+ , xx -+- (xx -+- ord' cc) ]++ , fastCanonicalVariations (ii -+- i_) == [ii -+- xx]+ , canonicalVariations ((i_ -+- i_) -+- (ord' c_ -+- ord' c_))+ == [ (xx -+- yy) -+- (ord' cc -+- ord' dd)+ , (xx -+- yy) -+- (ord' cc -+- ord' cc)+ , (xx -+- xx) -+- (ord' cc -+- ord' dd)+ , (xx -+- xx) -+- (ord' cc -+- ord' cc) ]++ , canonicalVariations (i_)+ == [ xx ]+ , canonicalVariations (i_ -+- i_)+ == [ xx -+- yy+ , xx -+- xx ]+ , canonicalVariations (i_ -+- i_ -+- i_)+ == [ xx -+- yy -+- zz+ , xx -+- yy -+- xx+ , xx -+- yy -+- yy+ , xx -+- xx -+- yy+ , xx -+- xx -+- xx+ ]+ , canonicalVariations (i_ -+- i_ -+- i_ -+- i_)+ == [ xx -+- yy -+- zz -+- xx'+ , xx -+- yy -+- zz -+- xx+ , xx -+- yy -+- zz -+- yy+ , xx -+- yy -+- zz -+- zz+ , xx -+- yy -+- xx -+- zz+ , xx -+- yy -+- xx -+- xx+ , xx -+- yy -+- xx -+- yy+ , xx -+- yy -+- yy -+- zz+ , xx -+- yy -+- yy -+- xx+ , xx -+- yy -+- yy -+- yy+ , xx -+- xx -+- yy -+- zz+ , xx -+- xx -+- yy -+- xx+ , xx -+- xx -+- yy -+- yy+ , xx -+- xx -+- xx -+- yy+ , xx -+- xx -+- xx -+- xx+ ]++ , holds n $ \e -> all isHole (vars e)+ ==> let xs = map (length . nubVars) $ canonicalVariations e+ in (head xs >) `all` tail xs+ && (last xs <) `all` init xs+ , holds n $ \e -> all isHole (vars e)+ ==> isNub (vars (head (canonicalVariations e)))+ , holds n $ \e -> all isHole (vars e)+ ==> let es = canonicalVariations e+ in (`isInstanceOf` head es) `all` tail es+ && (last es `isInstanceOf`) `all` init es+ , holds n $ \e -> let es = canonicalVariations e+ in length (nub (sort es)) == length es+ , holds n $ \e -> length (canonicalVariations e)+ == product (map (bell . snd) . counts $ holes e)+ ]++-- O(1) bell number implementation+-- only works up to 8+-- but this is enough for testing.+bell :: Int -> Int+bell 0 = 1+bell 1 = 1+bell 2 = 2+bell 3 = 5+bell 4 = 15+bell 5 = 52+bell 6 = 203+bell 7 = 877+bell 8 = 4140+bell _ = error "bell: argument > 8, implement me!"
+ test/core.hs view
@@ -0,0 +1,254 @@+-- Copyright (c) 2019 Rudy Matela. -- Distributed under the 3-Clause BSD licence (see the file LICENSE).+import Test++import Data.Express.Utils.List+import Test.LeanCheck.Error (errorToNothing)++main :: IO ()+main = mainTest tests 5040++tests :: Int -> [Bool]+tests n =+ [ True++ -- smart constructors and evaluation++ , holds n $ \x -> eval (undefined :: Int -> Int) (value "abs" (abs :: Int -> Int)) x == abs (x :: Int)+ , evl (val (10 :: Int)) == (10 :: Int)+ , evl (val (1337 :: Int)) == (1337 :: Int)+ , evl (val False) == False+ , holds n $ \x y -> evl (value "+" ((+) :: Int -> Int -> Int) :$ val x :$ val y) == (x + y :: Int)+ , holds n $ \x y -> evl (value "+" ((*) :: Int -> Int -> Int) :$ val x :$ val y) == (x * y :: Int)+ , holds n $ \i -> evl (val i) == (i :: Int)+ , show (one -+- one) == "1 + 1 :: Int"+ , show absE == "abs :: Int -> Int"+ , show notE == "not :: Bool -> Bool"+ , show andE == "(&&) :: Bool -> Bool -> Bool"+ , show (pp -&&- (not' false)) == "p && not False :: Bool"+ , show (one :$ one) == "1 1 :: ill-typed # Int $ Int #"+ , holds n $ \(IntE xx, IntE yy) -> isJust (toDynamic $ xx -+- yy)+ , holds n $ \(IntE xx, IntE yy) -> isGround xx && isGround yy+ ==> evl (xx -+- yy) =$ errorToNothing $= (evl (yy -+- xx) :: Int)++ -- valid applications+ , holds n $ \(IntToIntE ef) (IntE ex) -> isJust (ef $$ ex)+ , holds n $ \(BoolToBoolE ef) (BoolE ep) -> isJust (ef $$ ep)++ -- invalid applications+ , holds n $ \(IntE ex) (IntE ey) -> isNothing (ex $$ ey)+ , holds n $ \(BoolE ep) (BoolE eq) -> isNothing (ep $$ eq)+ , holds n $ \(BoolToBoolE ef) (IntE ex) -> isNothing (ef $$ ex)+ , holds n $ \(IntToIntE ef) (BoolE ep) -> isNothing (ef $$ ep)+ , holds n $ \(IntE ex) (IntE ey) (IntE ez) -> isNothing (ex $$ (ey :$ ez))+ , holds n $ \(IntE ex) (IntE ey) (IntE ez) -> isNothing ((ex :$ ey) $$ ez)+++ -- typing+ , typ zero == tyInt+ , typ one == tyInt+ , typ xx == tyInt+ , typ bee == tyChar+ , typ xxs == tyInts+ , typ (ff xx) == tyInt+ , typ (abs' one) == tyInt+ , typ true == tyBool+ , typ pp == tyBool++ , etyp zero == Right tyInt+ , etyp (abs' one) == Right tyInt+ , etyp (abs' bee) == Left (tyIntToInt, tyChar)+ , etyp (abs' bee :$ zero) == Left (tyIntToInt, tyChar)+ , etyp ((zero :$ one) :$ (bee :$ cee)) == Left (tyInt, tyInt)++ , etyp (xx :$ yy) == Left (tyInt, tyInt)+ , etyp (xx :$ (cc :$ yy)) == Left (tyChar, tyInt)+ , etyp (abs' xx :$ (ord' cc :$ negate' yy)) == Left (tyInt, tyInt)+ , holds n $ \(SameTypeE ef eg) (SameTypeE ex ey) -> (etyp (ef :$ ex) == etyp (eg :$ ey))+ , holds n $ \ef eg ex ey -> (etyp ef == etyp eg && etyp ex == etyp ey)+ == (etyp (ef :$ ex) == etyp (eg :$ ey))++ , isIllTyped (abs' zero) == False+ , isIllTyped (zero :$ one) == True+ , isWellTyped (abs' zero) == True+ , isWellTyped (zero :$ one) == False++ -- eq instance+ , xx -+- yy == xx -+- yy+ , xx -+- yy /= yy -+- xx+++ -- our Listable Expr enumeration does not produce ill typed Exprs+ , holds n $ isRight . etyp+ , holds n $ isJust . mtyp+ , holds n $ isWellTyped+ , holds n $ not . isIllTyped++ -- our Listable Ill enumeration only produces ill typed Exprs+ , holds n $ isLeft . etyp . unIll+ , holds n $ isNothing . mtyp . unIll+ , holds n $ isIllTyped . unIll+ , holds n $ not . isWellTyped . unIll++ -- we don't need the precondition here given the above+ -- but it's added just in case+ , holds n $ \e -> isRight (etyp e) ==> etyp e == Right (typ e)+ , holds n $ \e -> isJust (mtyp e) ==> mtyp e == Just (typ e)++ -- we prefer returning errors to the left+ , holds n $ \(Ill ef) (Ill ex) -> etyp (ef :$ ex) == etyp ef+ , holds n $ \ef (Ill ex) -> etyp (ef :$ ex) == etyp ex+++ -- boolean properties++ , hasVar (zero -+- one) == False+ , hasVar (xx -+- yy) == True++ , isGround (zero -+- (one -*- two)) == True+ , isGround (xx -+- (one -*- three)) == False++ , holds n $ isGround === not . hasVar++ -- isValue and isApp+ , holds n $ \e1 e2 -> isValue (e1 :$ e2) == False+ , holds n $ \e1 e2 -> isApp (e1 :$ e2) == True+ , holds n $ isValue === not . isApp+ , holds n $ isApp === not . isValue+ , holds n $ \e -> isValue e == (isVar e || isConst e)+ , holds n $ \e -> isApp e == (not (isVar e) && not (isConst e))++ , isVar xx == True+ , isVar yy == True+ , isVar ffE == True+ , isVar (xx -+- yy) == False+ , isVar (ff xx) == False+ , isVar one == False+ , isVar (one -+- two) == False++ , isHole i_ == True+ , isHole b_ == True+ , isHole xx == False++ , isConst xx == False+ , isConst yy == False+ , isConst (xx -+- yy) == False+ , isConst (ff xx) == False+ , isConst one == True+ , isConst two == True+ , isConst absE == True+ , isConst (one -+- two) == False++ , values (xx -+- yy) == [plus, xx, yy]+ , values (xx -+- (yy -+- zz)) == [plus, xx, plus, yy, zz]+ , values ((xx -+- yy) -+- zz) == [plus, plus, xx, yy, zz]+ , values (zero -+- (one -*- two)) == [plus, zero, times, one, two]+ , values (pp -&&- true) == [andE, pp, true]++ , subexprs (xx -+- yy) ==+ [ xx -+- yy+ , plus :$ xx+ , plus+ , xx+ , yy+ ]+ , subexprs (pp -&&- (pp -&&- true)) ==+ [ pp -&&- (pp -&&- true)+ , andE :$ pp+ , andE+ , pp+ , pp -&&- true+ , andE :$ pp+ , andE+ , pp+ , true+ ]+ , nubSubexprs (xx -+- yy) ==+ [ xx+ , yy+ , plus+ , plus :$ xx+ , xx -+- yy+ ]+ , nubSubexprs (pp -&&- (pp -&&- true)) ==+ [ pp+ , true+ , andE+ , andE :$ pp+ , pp -&&- true+ , pp -&&- (pp -&&- true)+ ]+++ -- boolean properties+ , holds n $ \e -> isHole e ==> isVar e++ -- listing subexpressions+ , holds n $ \e -> isGround e ==> consts e == values e++ , holds n $ \e -> nubSubexprs e `isSubsetOf` subexprs e+ , holds n $ \e -> nubValues e `isSubsetOf` values e+ , holds n $ \e -> nubVars e `isSubsetOf` vars e+ , holds n $ \e -> nubConsts e `isSubsetOf` consts e+ , holds n $ \e -> values e `isSubsetOf` subexprs e+ , holds n $ \e -> vars e `isSubsetOf` values e+ , holds n $ \e -> consts e `isSubsetOf` values e+ , holds n $ \e -> (vars e ++ consts e) `isPermutationOf` values e+ , holds n $ \e -> (nubVars e ++ nubConsts e) `isPermutationOf` nubValues e++ -- in case implementation changes+ , holds n $ \e -> nubSubexprs e == nubSort (subexprs e)+ , holds n $ \e -> nubValues e == nubSort (values e)+ , holds n $ \e -> nubVars e == nubSort (vars e)+ , holds n $ \e -> nubConsts e == nubSort (consts e)++ , arity zero == 0+ , arity xx == 0+ , arity absE == 1+ , arity plus == 2+ , arity times == 2++ , size zero == 1+ , size (one -+- two) == 3+ , size (abs' one) == 2++ , depth zero == 1+ , depth (one -+- two) == 2+ , depth (abs' one -+- two) == 3++ , height zero == 1+ , height (abs' one) == 2+ , height ((const' one) two) == 3+ , height ((const' (abs' one)) two) == 4+ , height ((const' one) (abs' two)) == 3++ , holds n $ \e -> depth e <= height e+ , holds n $ \e -> depth e <= size e+ , holds n $ \e -> height e <= size e++ , size zero == 1+ , depth zero == 1+ , size one == 1+ , depth one == 1+ , size (zero -+- one) == 3+ , depth (zero -+- one) == 2+ , size (zero -+- (xx -+- yy)) == 5+ , depth (zero -+- (xx -+- yy)) == 3+ , size (((xx -+- yy) -*- zz) -==- ((xx -*- zz) -+- (yy -*- zz))) == 13+ , depth (((xx -+- yy) -*- zz) -==- ((xx -*- zz) -+- (yy -*- zz))) == 4+ , depth (xx -*- yy -+- xx -*- zz -==- xx -*- (yy -+- zz)) == 4+ , size (xx -*- yy -+- xx -*- zz -==- xx -*- (yy -+- zz)) == 13+ , depth (xx -*- yy -+- xx -*- zz) == 3+ , depth (xx -*- (yy -+- zz)) == 3++ , nubConsts (xx -+- yy) == [plus]+ , nubConsts (xx -+- (yy -+- zz)) == [plus]+ , nubConsts (zero -+- one) =$ sort $= [zero, one, plus]+ , nubConsts ((zero -+- abs' zero) -+- (ord' ae -+- ord' cc))+ =$ sort $= [zero, ae, absE, plus, ordE]+ , holds n $ \e1 e2 -> times `elem` consts (e1 -*- e2)++ , vars (xx -+- yy) == [xx, yy]+ , nubVars (xx -+- xx) == [xx]+ , nubVars (xx -+- xx -+- yy) == [xx, yy]+ , nubVars (yy -+- xx -+- yy) == [xx, yy]+ ]
+ test/express-derive.hs view
@@ -0,0 +1,111 @@+-- Copyright (c) 2019 Rudy Matela.+-- Distributed under the 3-Clause BSD licence (see the file LICENSE).+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE DeriveDataTypeable #-}++import Test+++data Choice = Ae | Bee | Cee deriving (Show, Eq, Typeable)+data Peano = Zero | Succ Peano deriving (Show, Eq, Typeable)+data List a = a :- List a | Nil deriving (Show, Eq, Typeable)+data Bush a = Bush a :-: Bush a | Leaf a deriving (Show, Eq, Typeable)+data Tree a = Node (Tree a) a (Tree a) | Null deriving (Show, Eq, Typeable)++deriveExpress ''Choice+deriveExpress ''Peano+deriveExpress ''List+deriveExpress ''Bush+deriveExpress ''Tree++deriveListable ''Choice+deriveListable ''Peano+deriveListable ''List+deriveListable ''Bush+deriveListable ''Tree++-- Nested datatype cascade+data Nested = Nested N0 (N1 Int) (N2 Int Int) deriving (Eq, Show, Typeable)+data N0 = R0 Int deriving (Eq, Show, Typeable)+data N1 a = R1 a deriving (Eq, Show, Typeable)+data N2 a b = R2 a b deriving (Eq, Show, Typeable)++deriveExpressCascading ''Nested+deriveListableCascading ''Nested++-- Recursive nested datatype cascade+data RN = RN RN0 (RN1 Int) (RN2 Int RN) deriving (Eq, Show, Typeable)+data RN0 = Nest0 Int | Recurse0 RN deriving (Eq, Show, Typeable)+data RN1 a = Nest1 a | Recurse1 RN deriving (Eq, Show, Typeable)+data RN2 a b = Nest2 a b | Recurse2 RN deriving (Eq, Show, Typeable)+-- beware: values of the above type are always infinite!+-- derivation works but full evaluation does not terminate++deriveExpressCascading ''RN+deriveListableCascading ''RN++-- Those should have no effect (instance already exists):+{- uncommenting those should generate warnings+deriveExpress ''Bool+deriveExpress ''Maybe+deriveExpress ''Either+-}++-- Those should not generate warnings+deriveExpressIfNeeded ''Bool+deriveExpressIfNeeded ''Maybe+deriveExpressIfNeeded ''Either++data Mutual = Mutual0 | Mutual CoMutual deriving (Eq, Show, Typeable)+data CoMutual = CoMutual0 | CoMutual Mutual deriving (Eq, Show, Typeable)++deriveListableCascading ''Mutual+deriveExpressCascading ''Mutual+++main :: IO ()+main = mainTest tests 5040++tests :: Int -> [Bool]+tests n =+ [ True++ , holds n (exprIsVal :: Choice -> Bool)+ , fails n (exprIsVal :: Peano -> Bool)++ , fails n (exprIsVal :: List Int -> Bool)+ , fails n (exprIsVal :: List Bool -> Bool)++ , fails n (exprIsVal :: Bush Int -> Bool)+ , fails n (exprIsVal :: Bush Bool -> Bool)++ , fails n (exprIsVal :: Tree Int -> Bool)+ , fails n (exprIsVal :: Tree Bool -> Bool)++ , holds n (exprIsValUnderEvaluate :: Choice -> Bool)+ , holds n (exprIsValUnderEvaluate :: Peano -> Bool)++ , holds n (exprIsValUnderEvaluate :: List Int -> Bool)+ , holds n (exprIsValUnderEvaluate :: List Bool -> Bool)++ , holds n (exprIsValUnderEvaluate :: Bush Int -> Bool)+ , holds n (exprIsValUnderEvaluate :: Bush Bool -> Bool)++ , holds n (exprIsValUnderEvaluate :: Tree Int -> Bool)+ , holds n (exprIsValUnderEvaluate :: Tree Bool -> Bool)++ , holds n (exprIsValUnderEvaluate :: Nested -> Bool)+ , holds n (exprIsValUnderEvaluate :: N0 -> Bool)+ , holds n (exprIsValUnderEvaluate :: N1 Int -> Bool)+ , holds n (exprIsValUnderEvaluate :: N2 Int Bool -> Bool)++ , holds n (exprIsValUnderEvaluate :: Mutual -> Bool)+ , holds n (exprIsValUnderEvaluate :: CoMutual -> Bool)+ ]++-- not true in all cases+exprIsVal :: (Listable a, Express a, Show a) => a -> Bool+exprIsVal x = expr x == val x++exprIsValUnderEvaluate :: (Listable a, Express a, Show a, Eq a) => a -> Bool+exprIsValUnderEvaluate x = evaluate (expr x) == (evaluate (val x) -: mayb x)
+ test/express.hs view
@@ -0,0 +1,109 @@+-- Copyright (c) 2019 Rudy Matela.+-- Distributed under the 3-Clause BSD licence (see the file LICENSE).+{-# LANGUAGE CPP #-}+import Test++main :: IO ()+main = mainTest tests 5040++tests :: Int -> [Bool]+tests n =+ [ True++ , holds n $ \x -> expr x == val (x :: Int)+ , holds n $ \c -> expr c == val (c :: Char)+ , holds n $ \p -> expr p == val (p :: Bool)+ , holds n $ \x -> expr x == val (x :: ())+ , fails n $ \xs -> expr xs == val (xs :: [Int])+ , holds n $ expr ([] :: [Int]) == val ([] :: [Int])+ , holds n $ \x xs -> expr (x:xs) /= val (x:xs :: [Int])++ , holds n (okExpress :: () -> Bool)+ , holds n (okExpress :: Bool -> Bool)+ , holds n (okExpress :: Int -> Bool)+ , holds n (okExpress :: Integer -> Bool)+ , holds n (okExpress :: Char -> Bool)+ , holds n (okExpress :: Ordering -> Bool)++ , holds n (okExpress :: [Bool] -> Bool)+ , holds n (okExpress :: [Int] -> Bool)+ , holds n (okExpress :: [Integer] -> Bool)+ , holds n (okExpress :: [Char] -> Bool)+ , holds n (okExpress :: [Ordering] -> Bool)++ , holds n (okExpress :: ((),()) -> Bool)+ , holds n (okExpress :: (Bool,Bool) -> Bool)+ , holds n (okExpress :: (Int,Int) -> Bool)+ , holds n (okExpress :: ((),Bool) -> Bool)+ , holds n (okExpress :: (Bool,Int) -> Bool)++ , holds n (okExpress :: Maybe () -> Bool)+ , holds n (okExpress :: Maybe Bool -> Bool)+ , holds n (okExpress :: Maybe Int -> Bool)++ , holds n (okExpress :: Either () () -> Bool)+ , holds n (okExpress :: Either Bool Bool -> Bool)+ , holds n (okExpress :: Either Int Int -> Bool)+ , holds n (okExpress :: Either () Bool -> Bool)+ , holds n (okExpress :: Either Bool Int -> Bool)++ , holds n (okExpress :: (Int,Int,Int) -> Bool)+ , holds n (okExpress :: (Int,Int,Int,Int) -> Bool)+ , holds n (okExpress :: (Int,Int,Int,Int,Int) -> Bool)+ , holds n (okExpress :: (Int,Int,Int,Int,Int,Int) -> Bool)+ , holds n (okExpress :: (Int,Int,Int,Int,Int,Int,Int) -> Bool)+#if __GLASGOW_HASKELL__ < 710+-- No 8-tuples for you:+-- On GHC 7.8, 8-tuples are not Typeable instances. We could add a standalone+-- deriving clause, but that may cause trouble if some other library does the+-- same. User should declare Generalizable 8-tuples manually when using GHC <=+-- 7.8.+#else+ , holds n (okExpress :: (Int,Int,Int,Int,Int,Int,Int,Int) -> Bool)+ , holds n (okExpress :: (Int,Int,Int,Int,Int,Int,Int,Int,Int) -> Bool)+ , holds n (okExpress :: (Int,Int,Int,Int,Int,Int,Int,Int,Int,Int) -> Bool)+ , holds n (okExpress :: (Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int) -> Bool)+ , holds n (okExpress :: (Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int) -> Bool)+#endif++ -- Transforming lists into Exprs+ , expr ([]::[Int]) == value "[]" ([]::[Int])+ , expr ([0::Int]) == zero -:- nil+ , expr ([0::Int,1]) == zero -:- one -:- nil+ , holds n $ \xs -> expr xs == foldr (-:-) nil (map expr (xs :: [Int]))+ , holds n $ \ps -> expr ps == foldr (-:-) nilBool (map expr (ps :: [Bool]))++ -- Transforming Maybes into Exprs+ , expr (Nothing :: Maybe Int) == nothing+ , expr (Nothing :: Maybe Bool) == nothingBool+ , expr (Just 1 :: Maybe Int) == just one+ , expr (Just False :: Maybe Bool) == just false+ , holds n $ \x -> expr (Just x) == just (expr (x :: Int))+ , holds n $ \p -> expr (Just p) == just (expr (p :: Bool))++ -- Transforming Tuples into Exprs+ , expr ((0,False) :: (Int,Bool)) == pair zero false+ , expr ((True,1) :: (Bool,Int)) == pair true one++ -- Showing Exprs+ , holds n $ \x -> show (expr x) == show (x :: ()) ++ " :: ()"+ , holds n $ \x -> show (expr x) == show (x :: Int) ++ " :: Int"+ , holds n $ \p -> show (expr p) == show (p :: Bool) ++ " :: Bool"+ , holds n $ \x -> show (expr x) == show (x :: ((),Maybe Int,[Bool]))+ ++ " :: ((),(Maybe Int),[Bool])"+ ]++-- this is true only for some types+exprIsVal :: (Listable a, Express a, Show a) => a -> Bool+exprIsVal x = expr x == val x++-- this should be true for all types+exprIsValUnderEvaluate :: (Listable a, Express a, Show a, Eq a) => a -> Bool+exprIsValUnderEvaluate x = evaluate (expr x) == (evaluate (val x) -: mayb x)++-- this should be true for most types+showExprIsShow :: (Listable a, Express a, Show a) => a -> Bool+showExprIsShow x = showExpr (expr x) == show x++okExpress :: (Listable a, Express a, Show a, Eq a) => a -> Bool+okExpress = exprIsValUnderEvaluate &&& showExprIsShow
+ test/fixtures.hs view
@@ -0,0 +1,173 @@+-- Copyright (c) 2017-2018 Rudy Matela.+-- Distributed under the 3-Clause BSD licence (see the file LICENSE).+import Test++import Test.LeanCheck.Error (errorToNothing)++main :: IO ()+main = mainTest tests 5040++tests :: Int -> [Bool]+tests n =+ [ True++ -- Bool --++ , show b_ == "_ :: Bool"+ , show pp == "p :: Bool"+ , show qq == "q :: Bool"+ , show false == "False :: Bool"+ , show true == "True :: Bool"+ , show notE == "not :: Bool -> Bool"+ , show andE == "(&&) :: Bool -> Bool -> Bool"+ , show orE == "(||) :: Bool -> Bool -> Bool"+ , show (not' false) == "not False :: Bool"+ , show (false -&&- true) == "False && True :: Bool"+ , show (pp -||- false) == "p || False :: Bool"+ , show (qq -&&- true) == "q && True :: Bool"++ , evl false == False+ , evl true == True+ , holds n $ evl notE === not+ , holds n $ evl andE ==== (&&)+ , holds n $ evl orE ==== (||)+ , evl (not' false) == True+ , evl (false -&&- true) == False+ , evl (false -||- true) == True+ , holds n $ \p -> evl (not' (val p)) == not p+ , holds n $ \p q -> evl (val p -&&- val q) == (p && q)+ , holds n $ \p q -> evl (val p -||- val q) == (p || q)++ -- Int --++ , show i_ == "_ :: Int"+ , show xx == "x :: Int"+ , show yy == "y :: Int"+ , show zz == "z :: Int"+ , show xx' == "x' :: Int"+ , show zero == "0 :: Int"+ , show two == "2 :: Int"+ , show minusOne == "-1 :: Int"++ , show plus == "(+) :: Int -> Int -> Int"+ , show times == "(*) :: Int -> Int -> Int"+ , show (plus :$ one) == "(1 +) :: Int -> Int"+ , show (times :$ two) == "(2 *) :: Int -> Int"++ , show (one -+- one) == "1 + 1 :: Int"+ , show (minusOne -+- minusOne) == "(-1) + (-1) :: Int"+ , show (minusTwo -*- two) == "(-2) * 2 :: Int"+ , show (two -*- minusTwo) == "2 * (-2) :: Int"+ , show (xx -+- (yy -+- zz)) == "x + (y + z) :: Int"++ , evl zero == (0 :: Int)+ , evl one == (1 :: Int)+ , evl two == (2 :: Int)+ , evl three == (3 :: Int)+ , evl minusOne == (-1 :: Int)+ , evl minusTwo == (-2 :: Int)++ , evl (one -+- one) == (2 :: Int)+ , evl (two -*- three) == (6 :: Int)+ , holds n $ \x y -> evl (val x -+- val y) == (x + y :: Int)+ , holds n $ \x y -> evl (val x -*- val y) == (x * y :: Int)+ , holds n $ \(IntE ex) (IntE ey) -> isGround ex && isGround ey ==> evl (ex -+- ey) =$ errorToNothing $= evl ex + (evl ey :: Int)+ , holds n $ \(IntE ex) (IntE ey) -> isGround ex && isGround ey ==> evl (ex -*- ey) =$ errorToNothing $= evl ex * (evl ey :: Int)++ , show xxs == "xs :: [Int]"+ , show yys == "ys :: [Int]"+ , show nil == "[] :: [Int]"+ , show (unit one) == "[1] :: [Int]"++ -- Int -> Int --++ , show ffE == "f :: Int -> Int"+ , show ggE == "g :: Int -> Int"+ , show (ff xx) == "f x :: Int"+ , show (gg yy) == "g y :: Int"+ , show (ff one) == "f 1 :: Int"+ , show (gg minusTwo) == "g (-2) :: Int"++ , show idE == "id :: Int -> Int"+ , show negateE == "negate :: Int -> Int"+ , show absE == "abs :: Int -> Int"+ , show (id' yy) == "id y :: Int"+ , show (id' one) == "id 1 :: Int"+ , show (id' true) == "id True :: Bool"+ , show (negate' yy) == "negate y :: Int"+ , show (abs' xx') == "abs x' :: Int"++ , evl (id' one) == (1 :: Int)+ , evl (id' true) == (True :: Bool)+ , evl (negate' one) == (-1 :: Int)+ , evl (abs' minusTwo) == (2 :: Int)++ , evl nil == ([] :: [Int])+ , evl (unit one) == [1 :: Int]++ -- Int -> Int -> Int+ , show (var "?" (undefined :: Int->Int->Int)) == "(?) :: Int -> Int -> Int"+ , show (var "?" (undefined :: Int->Int->Int) :$ xx) == "(x ?) :: Int -> Int"+ , show (xx -?- yy) == "x ? y :: Int"+ , show (pp -?- qq) == "p ? q :: Bool"+ , show (xxs -?- yys) == "xs ? ys :: [Int]"+ , show (bee -?- cee) == "'b' ? 'c' :: Char"++ -- Char --++ , show c_ == "_ :: Char"+ , show bee == "'b' :: Char"+ , show cee == "'c' :: Char"+ , show dee == "'d' :: Char"++ , evl bee == 'b'+ , evl cee == 'c'+ , evl dee == 'd'+++ -- [a] & [Int] --++ , show xxs == "xs :: [Int]"+ , show yys == "ys :: [Int]"+ , show nil == "[] :: [Int]"+ , show cons == "(:) :: Int -> [Int] -> [Int]"+ , show (unit zero) == "[0] :: [Int]"+ , show (unit false) == "[False] :: [Bool]"+ , show (zero -:- one -:- unit two) == "[0,1,2] :: [Int]"+ , show (zero -:- one -:- two -:- nil) == "[0,1,2] :: [Int]"++ , evl nil == ([] :: [Int])+ , holds n $ \x -> evl (unit (val x)) == [x :: Int]+ , holds n $ \c -> evl (unit (val c)) == [c :: Char]+ , holds n $ \p -> evl (unit (val p)) == [p :: Bool]+ , holds n $ \x xs -> evl (val x -:- val xs) == (x:xs :: [Int])+ , holds n $ \p ps -> evl (val p -:- val ps) == (p:ps :: [Int])+ , holds n $ \c cs -> evl (val c -:- val cs) == (c:cs :: [Int])++ , show (nil -++- nil) == "[] ++ [] :: [Int]"+ , show ((zero -:- one -:- nil) -++- (two -:- three -:- nil)) == "[0,1] ++ [2,3] :: [Int]"++ , show (head' $ unit one) == "head [1] :: Int"+ , show (tail' $ unit one) == "tail [1] :: [Int]"+ , show (head' $ unit bee) == "head \"b\" :: Char"+ , show (tail' $ unit bee) == "tail \"b\" :: [Char]"+ , show (head' $ zero -:- unit two) == "head [0,2] :: Int"+ , show (tail' $ zero -:- unit two) == "tail [0,2] :: [Int]"++ , evl (unit one) == [1 :: Int]+ , evl (head' $ unit one) == (1 :: Int)+ , evl (tail' $ zero -:- unit two) == ([2] :: [Int])++ -- String --++ , show emptyString == "\"\" :: [Char]"+ , show (unit bee) == "\"b\" :: [Char]"+ , show (bee -:- unit cee) == "\"bc\" :: [Char]"+ , show (emptyString -++- emptyString) == "\"\" ++ \"\" :: [Char]"+ , show ((bee -:- unit cee) -++- unit dee) == "\"bc\" ++ \"d\" :: [Char]"++ , evl emptyString == ""+ , evl (unit bee) == "b"+ , evl (bee -:- unit cee) == "bc"+ , evl (bee -:- cee -:- unit dee) == "bcd"+ ]
+ test/fold.hs view
@@ -0,0 +1,34 @@+-- Copyright (c) 2019 Rudy Matela. -- Distributed under the 3-Clause BSD licence (see the file LICENSE).+import Test++main :: IO ()+main = mainTest tests 5040++tests :: Int -> [Bool]+tests n =+ [ True++ , holds n $ \e1 e2 -> (e1,e2) == unfoldPair (foldPair (e1,e2))+ , holds n $ \e123 -> e123 == unfoldTrio (foldTrio e123)++ -- the result of foldPair and foldTrio is always ill-typed+ , holds n $ \e1 e2 -> isIllTyped $ foldPair (e1,e2)+ , holds n $ \e123 -> isIllTyped $ foldTrio e123++ -- (==) works even though foldPair returns an ill-typed expression+ , holds n $ \e1 e2 -> foldPair (e1,e2) == foldPair (e1,e2)+ , fails n $ \e1 e2 -> foldPair (e1,e2) == foldPair (e2,e1)++ , show (foldPair (xx,yy)) == "(x,y) :: ill-typed # ExprPair $ Int #"+ , show (foldTrio (xx,yy,zz)) == "(x,y,z) :: ill-typed # ExprTrio $ Int #"++ , unfoldApp (abs' xx) == [absE, xx]+ , unfoldApp (abs' (xx -+- yy)) == [absE, xx -+- yy]+ , unfoldApp (xx -+- abs' xx) == [plus, xx, abs' xx]+ , unfoldApp one == [one]+ , unfoldApp false == [false]++ , holds n $ \e -> foldApp (unfoldApp e) == e++ , holds n $ \es -> es == unfold (fold es)+ ]
+ test/hole.hs view
@@ -0,0 +1,30 @@+-- Copyright (c) 2019 Rudy Matela.+-- Distributed under the 3-Clause BSD licence (see the file LICENSE).+import Test++main :: IO ()+main = mainTest tests 5040++tests :: Int -> [Bool]+tests n =+ [ True++ , isHole (hole (undefined :: Int)) == True+ , isHole (hole (undefined :: Bool)) == True+ , isHole (hole (undefined :: Char)) == True+ , holds n $ \x -> isHole (val (x :: Int)) == False+ , holds n $ \p -> isHole (val (p :: Bool)) == False+ , holds n $ \c -> isHole (val (c :: Char)) == False++ , holds n $ \e -> isHole e ==> isVar e+ , holds n $ \e1 e2 -> isHole (e1 :$ e2) == False++ , holds n $ \e -> holes e `isSubsequenceOf` vars e+ , holds n $ \e -> nubHoles e `isSubsetOf` holes e+ , holds n $ \e -> nubHoles e `isSubsequenceOf` nubVars e++ , [xx, yy, zz, xx'] `isPrefixOf` listVars "x" (undefined :: Int)+ , [pp, qq, rr, pp'] `isPrefixOf` listVars "p" (undefined :: Bool)+ , [xx, yy, zz, xx'] `isPrefixOf` listVarsAsTypeOf "x" zero+ , [pp, qq, rr, pp'] `isPrefixOf` listVarsAsTypeOf "p" false+ ]
+ test/instances.hs view
@@ -0,0 +1,51 @@+-- Copyright (c) 2017-2019 Rudy Matela.+-- Distributed under the 3-Clause BSD licence (see the file LICENSE).+{-# LANGUAGE NoMonomorphismRestriction #-} -- ACK!+import Test++main :: IO ()+main = mainTest tests 5040++tests :: Int -> [Bool]+tests n =+ [ True++ , eval undefined (eqFor (undefined :: Int) :$ one :$ one) == True+ , eval undefined (eqFor (undefined :: Int) :$ one :$ two) == False++ , eval undefined (lessEqFor (undefined :: Int) :$ one :$ two) == True+ , eval undefined (lessEqFor (undefined :: Int) :$ one :$ one) == True+ , eval undefined (lessEqFor (undefined :: Int) :$ two :$ one) == False++ , eval undefined (lessFor (undefined :: Int) :$ one :$ two) == True+ , eval undefined (lessFor (undefined :: Int) :$ one :$ one) == False+ , eval undefined (lessFor (undefined :: Int) :$ two :$ one) == False++-- for the time being, compare has been removed from reifyOrd's result+--, eval undefined (compareFor (undefined :: Int) :$ one :$ two) == LT+--, eval undefined (compareFor (undefined :: Int) :$ one :$ one) == EQ+--, eval undefined (compareFor (undefined :: Int) :$ two :$ one) == GT++ , eval undefined (nameFor (undefined :: Int) :$ xx) == "x"+ , eval undefined (nameFor (undefined :: Int) :$ yy) == "x"+ , eval undefined (nameFor (undefined :: Bool) :$ pp) == "p"+ , eval undefined (nameFor (undefined :: Bool) :$ qq) == "p"++ , length (validApps functions one) == 5+ ]+ where+ eqFor = head . reifyEq+ lessEqFor = head . reifyOrd+ lessFor = head . tail . reifyOrd+--compareFor = head . reifyOrd+ nameFor = head . reifyName++functions :: [Expr]+functions = concat+ [ reifyEq (undefined :: Int)+ , reifyEq (undefined :: Bool)+ , reifyOrd (undefined :: Int)+ , reifyOrd (undefined :: Bool)+ , reifyName (undefined :: Int)+ , reifyName (undefined :: Bool)+ ]
+ test/listable.hs view
@@ -0,0 +1,79 @@+-- Copyright (c) 2017-2018 Rudy Matela.+-- Distributed under the 3-Clause BSD licence (see the file LICENSE).+import Test++main :: IO ()+main = mainTest tests 5040++tests :: Int -> [Bool]+tests n =+ [ True++ -- Listable Expr only produces well-typed expressions+ , holds n $ isJust . toDynamic+ , holds n $ isJust . mtyp++ -- Listable Ill only produces ill-typed expressions+ , holds n $ isNothing . toDynamic . unIll+ , holds n $ isNothing . mtyp . unIll++ -- Listable TypeE produces expressions of the right type (evaluation)+ , holds n $ isJust . evaluateInt . unIntE+ , holds n $ isJust . evaluateBool . unBoolE+ , holds n $ isJust . evaluateInts . unIntsE+ , holds n $ isJust . evaluateIntToInt . unIntToIntE+ , holds n $ isJust . evaluateChar . unCharE+ , holds n $ \(IntToIntE ff) (IntE xx) -> isJust . evaluateInt $ ff :$ xx+ , holds n $ \(IntToIntToIntE ff) (IntE xx) (IntE yy) -> isJust . evaluateInt $ ff :$ xx :$ yy++ -- Listable TypeE produces expressions of the right type (typ)+ , holds n $ \(SameTypeE e1 e2) -> typ e1 == typ e2+ , holds n $ \(SameTypedPairsE ees) -> all (\(e1,e2) -> typ e1 == typ e2) ees+ , holds n $ \(IntE e) -> typ e == typ i_+ , holds n $ \(BoolE e) -> typ e == typ b_+ , holds n $ \(CharE e) -> typ e == typ c_+ , holds n $ \(IntsE e) -> typ e == typ is_++ -- Listable TypeE does not produce expressions of the wrong type+ , holds n $ isNothing . evaluateInt . unBoolE+ , holds n $ isNothing . evaluateBool . unIntE+ , holds n $ isNothing . evaluateInts . unIntE+ , holds n $ isNothing . evaluateIntToInt . unIntE+ , holds n $ isNothing . evaluateChar . unIntE++ -- Listable TypeE0 only returns terminal constants+ , holds n $ isConst . unE0+ , holds n $ isConst . unIntE0+ , holds n $ isConst . unBoolE0+ , holds n $ isConst . unIntsE0+ , holds n $ isConst . unCharE0++ -- Listable TypeEV only returns variables+ , holds n $ isVar . unEV+ , holds n $ isVar . unIntEV+ , holds n $ isVar . unBoolEV+ , holds n $ isVar . unIntsEV+ , holds n $ isVar . unCharEV++ -- counter-examples are of the right type+ , (counterExample n $ \(IntE xx) -> False) == Just ["_ :: Int"]++ , isNub (take (n`div`10) list :: [Expr])+ , isNub (take (n`div`10) $ map unSameTypeE list)+ , isNub (take (n`div`10) $ map unIntE list)+ ]++evaluateInt :: Expr -> Maybe Int+evaluateInt = evaluate++evaluateBool :: Expr -> Maybe Bool+evaluateBool = evaluate++evaluateInts :: Expr -> Maybe [Int]+evaluateInts = evaluate++evaluateIntToInt :: Expr -> Maybe (Int -> Int)+evaluateIntToInt = evaluate++evaluateChar :: Expr -> Maybe Char+evaluateChar = evaluate
+ test/main.hs view
@@ -0,0 +1,18 @@+-- Copyright (c) 2019 Rudy Matela. -- Distributed under the 3-Clause BSD licence (see the file LICENSE).+import Test++import Data.Express.Utils.List++main :: IO ()+main = mainTest tests 5040++tests :: Int -> [Bool]+tests n =+ [ True++ , evl (val (10 :: Int)) == (10 :: Int)+ , evl one == (1 :: Int)+ , holds n $ \x y -> evl (value "+" ((+) :: Int -> Int -> Int) :$ val x :$ val y) == (x + y :: Int)+ , values (xx -+- yy) == [plus, xx, yy]+ , (xx -+- yy) // [(yy,yy -+- zz),(xx,xx -+- yy)] == (xx -+- yy) -+- (yy -+- zz)+ ]
+ test/map.hs view
@@ -0,0 +1,101 @@+-- Copyright (c) 2019 Rudy Matela.+-- Distributed under the 3-Clause BSD licence (see the file LICENSE).+import Test+import Test.LeanCheck.Function++import Data.Express.Utils.List (isNub)++main :: IO ()+main = mainTest tests 5040++tests :: Int -> [Bool]+tests n =+ [ True++ -- the order should not matter for //+ , holds n $ \e ee1 ee2 -> fst ee1 /= fst ee2 ==> e // [ee1, ee2] == e // [ee2, ee1]+ , holds n $ \e ees -> isNub (map fst ees) ==> e // ees == e // reverse ees++ -- the order should not matter for //-+ , holds n $ \e ee1 ee2 -> fst ee1 /= fst ee2 ==> e //- [ee1, ee2] == e //- [ee2, ee1]+ , holds n $ \e ees -> isNub (map fst ees) ==> e //- ees == e //- reverse ees+ , holds n $ \e ees' -> let ees = map (mapFst unEV) ees' in+ isNub (map fst ees) ==> e //- ees == e //- reverse ees++ -- //- and // are essentially different+ , exists n $ \e es -> e // es /= e //- es++ -- equivalences between // and //-+ , holds n $ \e ees -> all (isValue . fst) ees ==> e // ees == e //- ees+ , holds n $ \e ees -> e // filter (isValue . fst) ees == e //- ees++ -- //- ignores replacements of non-variable values+ , holds n $ \e ees -> e //- filter (not . isValue . fst) ees == e++ -- (in)equivalences between maps+ , exists n $ \f e -> mapValues f e /= (mapVars f . mapConsts f) e+ , exists n $ \f e -> mapValues f e /= (mapConsts f . mapVars f) e+ , exists n $ \f e -> (mapVars f . mapConsts f) e /= (mapConsts f . mapVars f) e+ , exists n $ \f e -> (mapConsts f . mapVars f) e /= (mapVars f . mapConsts f) e+ -- the above should fail because of the following+ , let f _ = id' i_ in mapValues f zero == id' i_+ && mapVars f zero == zero+ && mapConsts f zero == id' i_+ && mapVars f (mapConsts f zero) == id' (id' i_)+ && mapConsts f (mapVars f zero) == id' i_++ -- the following do not hold in general:+ , exists n $ \f e -> (mapValues f . mapValues f) e /= mapValues f e+ , exists n $ \f e -> (mapVars f . mapVars f) e /= mapVars f e+ , exists n $ \f e -> (mapConsts f . mapConsts f) e /= mapConsts f e++ -- what actually holds is this:+ , holds n $ \f e -> (mapValues f . mapValues f) e == mapValues (mapValues f . f) e+ , holds n $ \f e -> (mapVars f . mapVars f) e == mapVars (mapVars f . f) e+ , holds n $ \f e -> (mapConsts f . mapConsts f) e == mapConsts (mapConsts f . f) e++ -- the following do not hold in general:+ , exists n $ \f e -> values (mapValues f e) /= map f (values e)+ , exists n $ \f e -> vars (mapVars f e) /= map f (vars e)+ , exists n $ \f e -> consts (mapConsts f e) /= map f (consts e)++ -- what actually holds is this:+ , holds n $ \f e -> values (mapValues f e) == concatMap (values . f) (values e)+ , holds n $ \f e -> vars (mapVars f e) == concatMap (vars . f) (vars e)+ , holds n $ \f e -> consts (mapConsts f e) == concatMap (consts . f) (consts e)++ -- tests of // and //-+ , ((xx -*- yy) -+- (yy -*- zz)) // [(xx,ii),(yy,jj),(zz,kk)] ==+ (ii -*- jj) -+- (jj -*- kk)++ , ((xx -*- yy) -+- (yy -*- zz)) //- [(xx,ii),(yy,jj),(zz,kk)] ==+ (ii -*- jj) -+- (jj -*- kk)++ , ((xx -*- yy) -+- (yy -*- zz)) // [(xx -*- yy,ii),(yy -*- zz,jj)] ==+ ii -+- jj++ , ((xx -*- yy) -+- (yy -*- zz)) //- [(xx -*- yy,ii),(yy -*- zz,jj)] ==+ (xx -*- yy) -+- (yy -*- zz)+++ , ((xx -+- yy) -+- (yy -+- zz)) // [(yy,yy -+- zz)]+ == (xx -+- (yy -+- zz)) -+- ((yy -+- zz) -+- zz)++ , ((xx -+- yy) -+- (yy -+- zz)) //- [(yy,yy -+- zz)]+ == (xx -+- (yy -+- zz)) -+- ((yy -+- zz) -+- zz)++ , (xx -+- yy) // [(yy,yy -+- zz),(xx,xx -+- yy)]+ == (xx -+- yy) -+- (yy -+- zz)++ , (xx -+- yy) //- [(yy,yy -+- zz),(xx,xx -+- yy)]+ == (xx -+- yy) -+- (yy -+- zz)++ , holds n $ \e -> renameVarsBy id e == e+ , holds n $ \c e -> (renameVarsBy tail . renameVarsBy (c:)) e == e+ , renameVarsBy (++ "1") (xx -+- yy) == (var "x1" int -+- var "y1" int)+ , renameVarsBy (\(c:cs) -> succ c:cs) ((xx -+- yy) -+- ord' cc)+ == ((yy -+- zz) -+- ord' dd)+ ]++mapFst :: (a -> c) -> (a,b) -> (c,b)+mapFst f (x,y) = (f x, y)
+ test/match.hs view
@@ -0,0 +1,57 @@+-- Copyright (c) 2019 Rudy Matela.+-- Distributed under the 3-Clause BSD licence (see the file LICENSE).+import Test++main :: IO ()+main = mainTest tests 5040++tests :: Int -> [Bool]+tests n =+ [ True++ , holds n $ \(IntE e) -> e `isInstanceOf` xx+ , holds n $ \(IntE e) -> abs' e `isInstanceOf` abs' xx+ , holds n $ \(IntE e) -> (e -+- e) `isInstanceOf` (xx -+- xx)+ , holds n $ \(IntE e1) (IntE e2) -> (e1 -+- e2) `isInstanceOf` (xx -+- yy)+ , holds n $ \(IntE e1) (IntE e2) -> e1 /= e2 ==> not ((e1 -+- e2) `isInstanceOf` (xx -+- xx))+ , holds n $ \e -> e /= zero ==> not (e `isInstanceOf` zero)++ , (zero -+- one) `isInstanceOf` (xx -+- yy)+ , (zero -+- zero) `isInstanceOf` (xx -+- yy)+ , (yy -+- xx) `isInstanceOf` (xx -+- yy)+ , (zero -+- zero) `isInstanceOf` (xx -+- xx)+ , not $ (zero -+- one) `isInstanceOf` (xx -+- xx)+ , zero `isInstanceOf` xx+ , not $ xx `isInstanceOf` zero+ , (xx -+- (yy -+- xx)) `isInstanceOf` (xx -+- yy)+ , (xx -+- (xx -+- xx)) `isInstanceOf` (xx -+- yy)+ , not $ (xx -+- (xx -+- xx)) `isInstanceOf` (xx -+- xx)++ , holds n $ \(IntE e1) (IntE e2) -> match (e1 -+- e2) (xx -+- yy) == Just [(yy,e2),(xx,e1)]+ , holds n $ \(IntE e) -> match (e -+- e) (xx -+- xx) == Just [(xx,e)]+ , holds n $ \(IntE e1) (IntE e2) -> e1 /= e2 ==> match (e1 -+- e2) (xx -+- xx) == Nothing+ , holds n $ \(IntE e1) (IntE e2) (IntE e3) -> e2 /= e3+ ==> match ((e1 -+- e1) -+- (e2 -+- e3)) (xx -+- (yy -+- yy)) == Nothing+ , holds n $ \(IntE e1) (IntE e2) -> matchWith [(xx,e1)] (e1 -+- e2) (xx -+- yy) == Just [(yy,e2),(xx,e1)]+ , holds n $ \(IntE e1) (IntE e2) -> e1 /= e2 ==> matchWith [(xx,e2)] (e1 -+- e2) (xx -+- yy) == Nothing+ , holds n $ \e1 e2 -> e1 `match` e2 == matchWith [] e1 e2+ , holds n $ \(SameTypeE e1 e2) (SameTypeE e3 e4) ->+ not (isFunTy $ typ e1) && not (isFunTy $ typ e3)+ ==>+ (e1 -==- e2) `match` (e3 -==- e4) == foldPair (e1,e2) `match` foldPair (e3,e4)++ -- tests for isSubexprOf --+ , holds n $ \e1 e2 -> e1 `isSubexprOf` e2 == (e1 `elem` subexprs e2)+ , holds n $ \e -> e `isSubexprOf` e+ , (xx -+- yy) `isSubexprOf` (zz -+- (xx -+- yy)) == True+ , (xx -+- yy) `isSubexprOf` abs' (yy -+- xx) == False+ , xx `isSubexprOf` yy == False+ , xx `isSubexprOf` xx == True++ -- tests of hasInstanceOf --+ , holds n $ \e1 e2 -> e1 `isInstanceOf` e2 ==> e1 `hasInstanceOf` e2+ , holds n $ \ef ex e -> ((ef :$ ex) `hasInstanceOf` e)+ == ((ef :$ ex) `isInstanceOf` e || ef `hasInstanceOf` e+ || ex `hasInstanceOf` e)+ , holds n $ \e1 e2 -> e1 `hasInstanceOf` e2 == any (`isInstanceOf` e2) (subexprs e1)+ ]
+ test/model/bench/compare.out view
@@ -0,0 +1,1001 @@+_ :: Int `compare` _ :: Int = EQ+_ :: Int `compare` x :: Int = LT+_ :: Int `compare` 0 :: Int = LT+_ :: Int `compare` id _ :: Int = LT+_ :: Int `compare` _ :: Bool = GT+_ :: Int `compare` _ :: Char = GT+_ :: Int `compare` _ :: [Int] = LT+x :: Int `compare` _ :: Int = GT+0 :: Int `compare` _ :: Int = GT+id _ :: Int `compare` _ :: Int = GT+_ :: Bool `compare` _ :: Int = LT+_ :: Char `compare` _ :: Int = LT+_ :: [Int] `compare` _ :: Int = GT+_ :: Int `compare` y :: Int = LT+_ :: Int `compare` 1 :: Int = LT+_ :: Int `compare` id x :: Int = LT+_ :: Int `compare` id 0 :: Int = LT+_ :: Int `compare` id (id _) :: Int = LT+_ :: Int `compare` negate _ :: Int = LT+_ :: Int `compare` abs _ :: Int = LT+_ :: Int `compare` _ + _ :: Int = LT+_ :: Int `compare` head _ :: Int = LT+_ :: Int `compare` ord _ :: Int = LT+_ :: Int `compare` p :: Bool = GT+_ :: Int `compare` False :: Bool = LT+_ :: Int `compare` True :: Bool = LT+_ :: Int `compare` not _ :: Bool = LT+_ :: Int `compare` c :: Char = GT+_ :: Int `compare` 'a' :: Char = LT+_ :: Int `compare` xs :: [Int] = LT+_ :: Int `compare` [] :: [Int] = LT+_ :: Int `compare` _:_ :: [Int] = LT+_ :: Int `compare` id :: Int -> Int = LT+_ :: Int `compare` (+) :: Int -> Int -> Int = LT+x :: Int `compare` x :: Int = EQ+x :: Int `compare` 0 :: Int = LT+x :: Int `compare` id _ :: Int = LT+x :: Int `compare` _ :: Bool = GT+x :: Int `compare` _ :: Char = GT+x :: Int `compare` _ :: [Int] = LT+0 :: Int `compare` x :: Int = GT+0 :: Int `compare` 0 :: Int = EQ+0 :: Int `compare` id _ :: Int = LT+0 :: Int `compare` _ :: Bool = GT+0 :: Int `compare` _ :: Char = GT+0 :: Int `compare` _ :: [Int] = GT+id _ :: Int `compare` x :: Int = GT+id _ :: Int `compare` 0 :: Int = GT+id _ :: Int `compare` id _ :: Int = EQ+id _ :: Int `compare` _ :: Bool = GT+id _ :: Int `compare` _ :: Char = GT+id _ :: Int `compare` _ :: [Int] = GT+_ :: Bool `compare` x :: Int = LT+_ :: Bool `compare` 0 :: Int = LT+_ :: Bool `compare` id _ :: Int = LT+_ :: Bool `compare` _ :: Bool = EQ+_ :: Bool `compare` _ :: Char = LT+_ :: Bool `compare` _ :: [Int] = LT+_ :: Char `compare` x :: Int = LT+_ :: Char `compare` 0 :: Int = LT+_ :: Char `compare` id _ :: Int = LT+_ :: Char `compare` _ :: Bool = GT+_ :: Char `compare` _ :: Char = EQ+_ :: Char `compare` _ :: [Int] = LT+_ :: [Int] `compare` x :: Int = GT+_ :: [Int] `compare` 0 :: Int = LT+_ :: [Int] `compare` id _ :: Int = LT+_ :: [Int] `compare` _ :: Bool = GT+_ :: [Int] `compare` _ :: Char = GT+_ :: [Int] `compare` _ :: [Int] = EQ+y :: Int `compare` _ :: Int = GT+1 :: Int `compare` _ :: Int = GT+id x :: Int `compare` _ :: Int = GT+id 0 :: Int `compare` _ :: Int = GT+id (id _) :: Int `compare` _ :: Int = GT+negate _ :: Int `compare` _ :: Int = GT+abs _ :: Int `compare` _ :: Int = GT+_ + _ :: Int `compare` _ :: Int = GT+head _ :: Int `compare` _ :: Int = GT+ord _ :: Int `compare` _ :: Int = GT+p :: Bool `compare` _ :: Int = LT+False :: Bool `compare` _ :: Int = GT+True :: Bool `compare` _ :: Int = GT+not _ :: Bool `compare` _ :: Int = GT+c :: Char `compare` _ :: Int = LT+'a' :: Char `compare` _ :: Int = GT+xs :: [Int] `compare` _ :: Int = GT+[] :: [Int] `compare` _ :: Int = GT+_:_ :: [Int] `compare` _ :: Int = GT+id :: Int -> Int `compare` _ :: Int = GT+(+) :: Int -> Int -> Int `compare` _ :: Int = GT+_ :: Int `compare` z :: Int = LT+_ :: Int `compare` -1 :: Int = LT+_ :: Int `compare` id y :: Int = LT+_ :: Int `compare` id 1 :: Int = LT+_ :: Int `compare` id (id x) :: Int = LT+_ :: Int `compare` id (id 0) :: Int = LT+_ :: Int `compare` id (id (id _)) :: Int = LT+_ :: Int `compare` id (negate _) :: Int = LT+_ :: Int `compare` id (abs _) :: Int = LT+_ :: Int `compare` id (_ + _) :: Int = LT+_ :: Int `compare` id (head _) :: Int = LT+_ :: Int `compare` id (ord _) :: Int = LT+_ :: Int `compare` negate x :: Int = LT+_ :: Int `compare` negate 0 :: Int = LT+_ :: Int `compare` negate (id _) :: Int = LT+_ :: Int `compare` abs x :: Int = LT+_ :: Int `compare` abs 0 :: Int = LT+_ :: Int `compare` abs (id _) :: Int = LT+_ :: Int `compare` _ + x :: Int = LT+_ :: Int `compare` _ + 0 :: Int = LT+_ :: Int `compare` _ + id _ :: Int = LT+_ :: Int `compare` x + _ :: Int = LT+_ :: Int `compare` 0 + _ :: Int = LT+_ :: Int `compare` id _ + _ :: Int = LT+_ :: Int `compare` _ * _ :: Int = LT+_ :: Int `compare` f _ :: Int = LT+_ :: Int `compare` head xs :: Int = LT+_ :: Int `compare` head [] :: Int = LT+_ :: Int `compare` head (_:_) :: Int = LT+_ :: Int `compare` ord c :: Int = LT+_ :: Int `compare` ord 'a' :: Int = LT+_ :: Int `compare` q :: Bool = GT+_ :: Int `compare` not p :: Bool = LT+_ :: Int `compare` not False :: Bool = LT+_ :: Int `compare` not True :: Bool = LT+_ :: Int `compare` not (not _) :: Bool = LT+_ :: Int `compare` _ || _ :: Bool = LT+_ :: Int `compare` d :: Char = GT+_ :: Int `compare` ' ' :: Char = LT+_ :: Int `compare` ys :: [Int] = LT+_ :: Int `compare` [0] :: [Int] = LT+_ :: Int `compare` _:xs :: [Int] = LT+_ :: Int `compare` [_] :: [Int] = LT+_ :: Int `compare` _:_:_ :: [Int] = LT+_ :: Int `compare` x:_ :: [Int] = LT+_ :: Int `compare` 0:_ :: [Int] = LT+_ :: Int `compare` id _:_ :: [Int] = LT+_ :: Int `compare` tail _ :: [Int] = LT+_ :: Int `compare` _ ++ _ :: [Int] = LT+_ :: Int `compare` negate :: Int -> Int = LT+_ :: Int `compare` abs :: Int -> Int = LT+_ :: Int `compare` (_ +) :: Int -> Int = LT+_ :: Int `compare` (*) :: Int -> Int -> Int = LT+_ :: Int `compare` not :: Bool -> Bool = LT+_ :: Int `compare` (||) :: Bool -> Bool -> Bool = LT+x :: Int `compare` y :: Int = LT+x :: Int `compare` 1 :: Int = LT+x :: Int `compare` id x :: Int = LT+x :: Int `compare` id 0 :: Int = LT+x :: Int `compare` id (id _) :: Int = LT+x :: Int `compare` negate _ :: Int = LT+x :: Int `compare` abs _ :: Int = LT+x :: Int `compare` _ + _ :: Int = LT+x :: Int `compare` head _ :: Int = LT+x :: Int `compare` ord _ :: Int = LT+x :: Int `compare` p :: Bool = GT+x :: Int `compare` False :: Bool = LT+x :: Int `compare` True :: Bool = LT+x :: Int `compare` not _ :: Bool = LT+x :: Int `compare` c :: Char = GT+x :: Int `compare` 'a' :: Char = LT+x :: Int `compare` xs :: [Int] = LT+x :: Int `compare` [] :: [Int] = LT+x :: Int `compare` _:_ :: [Int] = LT+x :: Int `compare` id :: Int -> Int = LT+x :: Int `compare` (+) :: Int -> Int -> Int = LT+0 :: Int `compare` y :: Int = GT+0 :: Int `compare` 1 :: Int = LT+0 :: Int `compare` id x :: Int = LT+0 :: Int `compare` id 0 :: Int = LT+0 :: Int `compare` id (id _) :: Int = LT+0 :: Int `compare` negate _ :: Int = LT+0 :: Int `compare` abs _ :: Int = LT+0 :: Int `compare` _ + _ :: Int = LT+0 :: Int `compare` head _ :: Int = LT+0 :: Int `compare` ord _ :: Int = LT+0 :: Int `compare` p :: Bool = GT+0 :: Int `compare` False :: Bool = GT+0 :: Int `compare` True :: Bool = GT+0 :: Int `compare` not _ :: Bool = LT+0 :: Int `compare` c :: Char = GT+0 :: Int `compare` 'a' :: Char = GT+0 :: Int `compare` xs :: [Int] = GT+0 :: Int `compare` [] :: [Int] = LT+0 :: Int `compare` _:_ :: [Int] = LT+0 :: Int `compare` id :: Int -> Int = LT+0 :: Int `compare` (+) :: Int -> Int -> Int = LT+id _ :: Int `compare` y :: Int = GT+id _ :: Int `compare` 1 :: Int = GT+id _ :: Int `compare` id x :: Int = LT+id _ :: Int `compare` id 0 :: Int = LT+id _ :: Int `compare` id (id _) :: Int = LT+id _ :: Int `compare` negate _ :: Int = LT+id _ :: Int `compare` abs _ :: Int = GT+id _ :: Int `compare` _ + _ :: Int = LT+id _ :: Int `compare` head _ :: Int = LT+id _ :: Int `compare` ord _ :: Int = GT+id _ :: Int `compare` p :: Bool = GT+id _ :: Int `compare` False :: Bool = GT+id _ :: Int `compare` True :: Bool = GT+id _ :: Int `compare` not _ :: Bool = GT+id _ :: Int `compare` c :: Char = GT+id _ :: Int `compare` 'a' :: Char = GT+id _ :: Int `compare` xs :: [Int] = GT+id _ :: Int `compare` [] :: [Int] = GT+id _ :: Int `compare` _:_ :: [Int] = LT+id _ :: Int `compare` id :: Int -> Int = GT+id _ :: Int `compare` (+) :: Int -> Int -> Int = GT+_ :: Bool `compare` y :: Int = LT+_ :: Bool `compare` 1 :: Int = LT+_ :: Bool `compare` id x :: Int = LT+_ :: Bool `compare` id 0 :: Int = LT+_ :: Bool `compare` id (id _) :: Int = LT+_ :: Bool `compare` negate _ :: Int = LT+_ :: Bool `compare` abs _ :: Int = LT+_ :: Bool `compare` _ + _ :: Int = LT+_ :: Bool `compare` head _ :: Int = LT+_ :: Bool `compare` ord _ :: Int = LT+_ :: Bool `compare` p :: Bool = LT+_ :: Bool `compare` False :: Bool = LT+_ :: Bool `compare` True :: Bool = LT+_ :: Bool `compare` not _ :: Bool = LT+_ :: Bool `compare` c :: Char = LT+_ :: Bool `compare` 'a' :: Char = LT+_ :: Bool `compare` xs :: [Int] = LT+_ :: Bool `compare` [] :: [Int] = LT+_ :: Bool `compare` _:_ :: [Int] = LT+_ :: Bool `compare` id :: Int -> Int = LT+_ :: Bool `compare` (+) :: Int -> Int -> Int = LT+_ :: Char `compare` y :: Int = LT+_ :: Char `compare` 1 :: Int = LT+_ :: Char `compare` id x :: Int = LT+_ :: Char `compare` id 0 :: Int = LT+_ :: Char `compare` id (id _) :: Int = LT+_ :: Char `compare` negate _ :: Int = LT+_ :: Char `compare` abs _ :: Int = LT+_ :: Char `compare` _ + _ :: Int = LT+_ :: Char `compare` head _ :: Int = LT+_ :: Char `compare` ord _ :: Int = LT+_ :: Char `compare` p :: Bool = GT+_ :: Char `compare` False :: Bool = LT+_ :: Char `compare` True :: Bool = LT+_ :: Char `compare` not _ :: Bool = LT+_ :: Char `compare` c :: Char = LT+_ :: Char `compare` 'a' :: Char = LT+_ :: Char `compare` xs :: [Int] = LT+_ :: Char `compare` [] :: [Int] = LT+_ :: Char `compare` _:_ :: [Int] = LT+_ :: Char `compare` id :: Int -> Int = LT+_ :: Char `compare` (+) :: Int -> Int -> Int = LT+_ :: [Int] `compare` y :: Int = GT+_ :: [Int] `compare` 1 :: Int = LT+_ :: [Int] `compare` id x :: Int = LT+_ :: [Int] `compare` id 0 :: Int = LT+_ :: [Int] `compare` id (id _) :: Int = LT+_ :: [Int] `compare` negate _ :: Int = LT+_ :: [Int] `compare` abs _ :: Int = LT+_ :: [Int] `compare` _ + _ :: Int = LT+_ :: [Int] `compare` head _ :: Int = LT+_ :: [Int] `compare` ord _ :: Int = LT+_ :: [Int] `compare` p :: Bool = GT+_ :: [Int] `compare` False :: Bool = LT+_ :: [Int] `compare` True :: Bool = LT+_ :: [Int] `compare` not _ :: Bool = LT+_ :: [Int] `compare` c :: Char = GT+_ :: [Int] `compare` 'a' :: Char = LT+_ :: [Int] `compare` xs :: [Int] = LT+_ :: [Int] `compare` [] :: [Int] = LT+_ :: [Int] `compare` _:_ :: [Int] = LT+_ :: [Int] `compare` id :: Int -> Int = LT+_ :: [Int] `compare` (+) :: Int -> Int -> Int = LT+y :: Int `compare` x :: Int = GT+y :: Int `compare` 0 :: Int = LT+y :: Int `compare` id _ :: Int = LT+y :: Int `compare` _ :: Bool = GT+y :: Int `compare` _ :: Char = GT+y :: Int `compare` _ :: [Int] = LT+1 :: Int `compare` x :: Int = GT+1 :: Int `compare` 0 :: Int = GT+1 :: Int `compare` id _ :: Int = LT+1 :: Int `compare` _ :: Bool = GT+1 :: Int `compare` _ :: Char = GT+1 :: Int `compare` _ :: [Int] = GT+id x :: Int `compare` x :: Int = GT+id x :: Int `compare` 0 :: Int = GT+id x :: Int `compare` id _ :: Int = GT+id x :: Int `compare` _ :: Bool = GT+id x :: Int `compare` _ :: Char = GT+id x :: Int `compare` _ :: [Int] = GT+id 0 :: Int `compare` x :: Int = GT+id 0 :: Int `compare` 0 :: Int = GT+id 0 :: Int `compare` id _ :: Int = GT+id 0 :: Int `compare` _ :: Bool = GT+id 0 :: Int `compare` _ :: Char = GT+id 0 :: Int `compare` _ :: [Int] = GT+id (id _) :: Int `compare` x :: Int = GT+id (id _) :: Int `compare` 0 :: Int = GT+id (id _) :: Int `compare` id _ :: Int = GT+id (id _) :: Int `compare` _ :: Bool = GT+id (id _) :: Int `compare` _ :: Char = GT+id (id _) :: Int `compare` _ :: [Int] = GT+negate _ :: Int `compare` x :: Int = GT+negate _ :: Int `compare` 0 :: Int = GT+negate _ :: Int `compare` id _ :: Int = GT+negate _ :: Int `compare` _ :: Bool = GT+negate _ :: Int `compare` _ :: Char = GT+negate _ :: Int `compare` _ :: [Int] = GT+abs _ :: Int `compare` x :: Int = GT+abs _ :: Int `compare` 0 :: Int = GT+abs _ :: Int `compare` id _ :: Int = LT+abs _ :: Int `compare` _ :: Bool = GT+abs _ :: Int `compare` _ :: Char = GT+abs _ :: Int `compare` _ :: [Int] = GT+_ + _ :: Int `compare` x :: Int = GT+_ + _ :: Int `compare` 0 :: Int = GT+_ + _ :: Int `compare` id _ :: Int = GT+_ + _ :: Int `compare` _ :: Bool = GT+_ + _ :: Int `compare` _ :: Char = GT+_ + _ :: Int `compare` _ :: [Int] = GT+head _ :: Int `compare` x :: Int = GT+head _ :: Int `compare` 0 :: Int = GT+head _ :: Int `compare` id _ :: Int = GT+head _ :: Int `compare` _ :: Bool = GT+head _ :: Int `compare` _ :: Char = GT+head _ :: Int `compare` _ :: [Int] = GT+ord _ :: Int `compare` x :: Int = GT+ord _ :: Int `compare` 0 :: Int = GT+ord _ :: Int `compare` id _ :: Int = LT+ord _ :: Int `compare` _ :: Bool = GT+ord _ :: Int `compare` _ :: Char = GT+ord _ :: Int `compare` _ :: [Int] = GT+p :: Bool `compare` x :: Int = LT+p :: Bool `compare` 0 :: Int = LT+p :: Bool `compare` id _ :: Int = LT+p :: Bool `compare` _ :: Bool = GT+p :: Bool `compare` _ :: Char = LT+p :: Bool `compare` _ :: [Int] = LT+False :: Bool `compare` x :: Int = GT+False :: Bool `compare` 0 :: Int = LT+False :: Bool `compare` id _ :: Int = LT+False :: Bool `compare` _ :: Bool = GT+False :: Bool `compare` _ :: Char = GT+False :: Bool `compare` _ :: [Int] = GT+True :: Bool `compare` x :: Int = GT+True :: Bool `compare` 0 :: Int = LT+True :: Bool `compare` id _ :: Int = LT+True :: Bool `compare` _ :: Bool = GT+True :: Bool `compare` _ :: Char = GT+True :: Bool `compare` _ :: [Int] = GT+not _ :: Bool `compare` x :: Int = GT+not _ :: Bool `compare` 0 :: Int = GT+not _ :: Bool `compare` id _ :: Int = LT+not _ :: Bool `compare` _ :: Bool = GT+not _ :: Bool `compare` _ :: Char = GT+not _ :: Bool `compare` _ :: [Int] = GT+c :: Char `compare` x :: Int = LT+c :: Char `compare` 0 :: Int = LT+c :: Char `compare` id _ :: Int = LT+c :: Char `compare` _ :: Bool = GT+c :: Char `compare` _ :: Char = GT+c :: Char `compare` _ :: [Int] = LT+'a' :: Char `compare` x :: Int = GT+'a' :: Char `compare` 0 :: Int = LT+'a' :: Char `compare` id _ :: Int = LT+'a' :: Char `compare` _ :: Bool = GT+'a' :: Char `compare` _ :: Char = GT+'a' :: Char `compare` _ :: [Int] = GT+xs :: [Int] `compare` x :: Int = GT+xs :: [Int] `compare` 0 :: Int = LT+xs :: [Int] `compare` id _ :: Int = LT+xs :: [Int] `compare` _ :: Bool = GT+xs :: [Int] `compare` _ :: Char = GT+xs :: [Int] `compare` _ :: [Int] = GT+[] :: [Int] `compare` x :: Int = GT+[] :: [Int] `compare` 0 :: Int = GT+[] :: [Int] `compare` id _ :: Int = LT+[] :: [Int] `compare` _ :: Bool = GT+[] :: [Int] `compare` _ :: Char = GT+[] :: [Int] `compare` _ :: [Int] = GT+_:_ :: [Int] `compare` x :: Int = GT+_:_ :: [Int] `compare` 0 :: Int = GT+_:_ :: [Int] `compare` id _ :: Int = GT+_:_ :: [Int] `compare` _ :: Bool = GT+_:_ :: [Int] `compare` _ :: Char = GT+_:_ :: [Int] `compare` _ :: [Int] = GT+id :: Int -> Int `compare` x :: Int = GT+id :: Int -> Int `compare` 0 :: Int = GT+id :: Int -> Int `compare` id _ :: Int = LT+id :: Int -> Int `compare` _ :: Bool = GT+id :: Int -> Int `compare` _ :: Char = GT+id :: Int -> Int `compare` _ :: [Int] = GT+(+) :: Int -> Int -> Int `compare` x :: Int = GT+(+) :: Int -> Int -> Int `compare` 0 :: Int = GT+(+) :: Int -> Int -> Int `compare` id _ :: Int = LT+(+) :: Int -> Int -> Int `compare` _ :: Bool = GT+(+) :: Int -> Int -> Int `compare` _ :: Char = GT+(+) :: Int -> Int -> Int `compare` _ :: [Int] = GT+z :: Int `compare` _ :: Int = GT+-1 :: Int `compare` _ :: Int = GT+id y :: Int `compare` _ :: Int = GT+id 1 :: Int `compare` _ :: Int = GT+id (id x) :: Int `compare` _ :: Int = GT+id (id 0) :: Int `compare` _ :: Int = GT+id (id (id _)) :: Int `compare` _ :: Int = GT+id (negate _) :: Int `compare` _ :: Int = GT+id (abs _) :: Int `compare` _ :: Int = GT+id (_ + _) :: Int `compare` _ :: Int = GT+id (head _) :: Int `compare` _ :: Int = GT+id (ord _) :: Int `compare` _ :: Int = GT+negate x :: Int `compare` _ :: Int = GT+negate 0 :: Int `compare` _ :: Int = GT+negate (id _) :: Int `compare` _ :: Int = GT+abs x :: Int `compare` _ :: Int = GT+abs 0 :: Int `compare` _ :: Int = GT+abs (id _) :: Int `compare` _ :: Int = GT+_ + x :: Int `compare` _ :: Int = GT+_ + 0 :: Int `compare` _ :: Int = GT+_ + id _ :: Int `compare` _ :: Int = GT+x + _ :: Int `compare` _ :: Int = GT+0 + _ :: Int `compare` _ :: Int = GT+id _ + _ :: Int `compare` _ :: Int = GT+_ * _ :: Int `compare` _ :: Int = GT+f _ :: Int `compare` _ :: Int = GT+head xs :: Int `compare` _ :: Int = GT+head [] :: Int `compare` _ :: Int = GT+head (_:_) :: Int `compare` _ :: Int = GT+ord c :: Int `compare` _ :: Int = GT+ord 'a' :: Int `compare` _ :: Int = GT+q :: Bool `compare` _ :: Int = LT+not p :: Bool `compare` _ :: Int = GT+not False :: Bool `compare` _ :: Int = GT+not True :: Bool `compare` _ :: Int = GT+not (not _) :: Bool `compare` _ :: Int = GT+_ || _ :: Bool `compare` _ :: Int = GT+d :: Char `compare` _ :: Int = LT+' ' :: Char `compare` _ :: Int = GT+ys :: [Int] `compare` _ :: Int = GT+[0] :: [Int] `compare` _ :: Int = GT+_:xs :: [Int] `compare` _ :: Int = GT+[_] :: [Int] `compare` _ :: Int = GT+_:_:_ :: [Int] `compare` _ :: Int = GT+x:_ :: [Int] `compare` _ :: Int = GT+0:_ :: [Int] `compare` _ :: Int = GT+id _:_ :: [Int] `compare` _ :: Int = GT+tail _ :: [Int] `compare` _ :: Int = GT+_ ++ _ :: [Int] `compare` _ :: Int = GT+negate :: Int -> Int `compare` _ :: Int = GT+abs :: Int -> Int `compare` _ :: Int = GT+(_ +) :: Int -> Int `compare` _ :: Int = GT+(*) :: Int -> Int -> Int `compare` _ :: Int = GT+not :: Bool -> Bool `compare` _ :: Int = GT+(||) :: Bool -> Bool -> Bool `compare` _ :: Int = GT+_ :: Int `compare` x' :: Int = LT+_ :: Int `compare` 2 :: Int = LT+_ :: Int `compare` id z :: Int = LT+_ :: Int `compare` id (-1) :: Int = LT+_ :: Int `compare` id (id y) :: Int = LT+_ :: Int `compare` id (id 1) :: Int = LT+_ :: Int `compare` id (id (id x)) :: Int = LT+_ :: Int `compare` id (id (id 0)) :: Int = LT+_ :: Int `compare` id (id (id (id _))) :: Int = LT+_ :: Int `compare` id (id (negate _)) :: Int = LT+_ :: Int `compare` id (id (abs _)) :: Int = LT+_ :: Int `compare` id (id (_ + _)) :: Int = LT+_ :: Int `compare` id (id (head _)) :: Int = LT+_ :: Int `compare` id (id (ord _)) :: Int = LT+_ :: Int `compare` id (negate x) :: Int = LT+_ :: Int `compare` id (negate 0) :: Int = LT+_ :: Int `compare` id (negate (id _)) :: Int = LT+_ :: Int `compare` id (abs x) :: Int = LT+_ :: Int `compare` id (abs 0) :: Int = LT+_ :: Int `compare` id (abs (id _)) :: Int = LT+_ :: Int `compare` id (_ + x) :: Int = LT+_ :: Int `compare` id (_ + 0) :: Int = LT+_ :: Int `compare` id (_ + id _) :: Int = LT+_ :: Int `compare` id (x + _) :: Int = LT+_ :: Int `compare` id (0 + _) :: Int = LT+_ :: Int `compare` id (id _ + _) :: Int = LT+_ :: Int `compare` id (_ * _) :: Int = LT+_ :: Int `compare` id (f _) :: Int = LT+_ :: Int `compare` id (head xs) :: Int = LT+_ :: Int `compare` id (head []) :: Int = LT+_ :: Int `compare` id (head (_:_)) :: Int = LT+_ :: Int `compare` id (ord c) :: Int = LT+_ :: Int `compare` id (ord 'a') :: Int = LT+_ :: Int `compare` negate y :: Int = LT+_ :: Int `compare` negate 1 :: Int = LT+_ :: Int `compare` negate (id x) :: Int = LT+_ :: Int `compare` negate (id 0) :: Int = LT+_ :: Int `compare` negate (id (id _)) :: Int = LT+_ :: Int `compare` negate (negate _) :: Int = LT+_ :: Int `compare` negate (abs _) :: Int = LT+_ :: Int `compare` negate (_ + _) :: Int = LT+_ :: Int `compare` negate (head _) :: Int = LT+_ :: Int `compare` negate (ord _) :: Int = LT+_ :: Int `compare` abs y :: Int = LT+_ :: Int `compare` abs 1 :: Int = LT+_ :: Int `compare` abs (id x) :: Int = LT+_ :: Int `compare` abs (id 0) :: Int = LT+_ :: Int `compare` abs (id (id _)) :: Int = LT+_ :: Int `compare` abs (negate _) :: Int = LT+_ :: Int `compare` abs (abs _) :: Int = LT+_ :: Int `compare` abs (_ + _) :: Int = LT+_ :: Int `compare` abs (head _) :: Int = LT+_ :: Int `compare` abs (ord _) :: Int = LT+_ :: Int `compare` _ + y :: Int = LT+_ :: Int `compare` _ + 1 :: Int = LT+_ :: Int `compare` _ + id x :: Int = LT+_ :: Int `compare` _ + id 0 :: Int = LT+_ :: Int `compare` _ + id (id _) :: Int = LT+_ :: Int `compare` _ + negate _ :: Int = LT+_ :: Int `compare` _ + abs _ :: Int = LT+_ :: Int `compare` _ + (_ + _) :: Int = LT+_ :: Int `compare` _ + head _ :: Int = LT+_ :: Int `compare` _ + ord _ :: Int = LT+_ :: Int `compare` x + x :: Int = LT+_ :: Int `compare` x + 0 :: Int = LT+_ :: Int `compare` x + id _ :: Int = LT+_ :: Int `compare` 0 + x :: Int = LT+_ :: Int `compare` 0 + 0 :: Int = LT+_ :: Int `compare` 0 + id _ :: Int = LT+_ :: Int `compare` id _ + x :: Int = LT+_ :: Int `compare` id _ + 0 :: Int = LT+_ :: Int `compare` id _ + id _ :: Int = LT+_ :: Int `compare` _ * x :: Int = LT+_ :: Int `compare` _ * 0 :: Int = LT+_ :: Int `compare` _ * id _ :: Int = LT+_ :: Int `compare` f x :: Int = LT+_ :: Int `compare` f 0 :: Int = LT+_ :: Int `compare` f (id _) :: Int = LT+_ :: Int `compare` y + _ :: Int = LT+_ :: Int `compare` 1 + _ :: Int = LT+_ :: Int `compare` id x + _ :: Int = LT+_ :: Int `compare` id 0 + _ :: Int = LT+_ :: Int `compare` id (id _) + _ :: Int = LT+_ :: Int `compare` negate _ + _ :: Int = LT+_ :: Int `compare` abs _ + _ :: Int = LT+_ :: Int `compare` (_ + _) + _ :: Int = LT+_ :: Int `compare` head _ + _ :: Int = LT+_ :: Int `compare` ord _ + _ :: Int = LT+_ :: Int `compare` x * _ :: Int = LT+_ :: Int `compare` 0 * _ :: Int = LT+_ :: Int `compare` id _ * _ :: Int = LT+_ :: Int `compare` g _ :: Int = LT+_ :: Int `compare` head ys :: Int = LT+_ :: Int `compare` head [0] :: Int = LT+_ :: Int `compare` head (_:xs) :: Int = LT+_ :: Int `compare` head [_] :: Int = LT+_ :: Int `compare` head (_:_:_) :: Int = LT+_ :: Int `compare` head (x:_) :: Int = LT+_ :: Int `compare` head (0:_) :: Int = LT+_ :: Int `compare` head (id _:_) :: Int = LT+_ :: Int `compare` head (tail _) :: Int = LT+_ :: Int `compare` head (_ ++ _) :: Int = LT+_ :: Int `compare` ord d :: Int = LT+_ :: Int `compare` ord ' ' :: Int = LT+_ :: Int `compare` r :: Bool = GT+_ :: Int `compare` not q :: Bool = LT+_ :: Int `compare` not (not p) :: Bool = LT+_ :: Int `compare` not (not False) :: Bool = LT+_ :: Int `compare` not (not True) :: Bool = LT+_ :: Int `compare` not (not (not _)) :: Bool = LT+_ :: Int `compare` not (_ || _) :: Bool = LT+_ :: Int `compare` _ || p :: Bool = LT+_ :: Int `compare` _ || False :: Bool = LT+_ :: Int `compare` _ || True :: Bool = LT+_ :: Int `compare` _ || not _ :: Bool = LT+_ :: Int `compare` p || _ :: Bool = LT+_ :: Int `compare` False || _ :: Bool = LT+_ :: Int `compare` True || _ :: Bool = LT+_ :: Int `compare` not _ || _ :: Bool = LT+_ :: Int `compare` _ && _ :: Bool = LT+_ :: Int `compare` _ == _ :: Bool = LT+_ :: Int `compare` _ == _ :: Bool = LT+_ :: Int `compare` odd _ :: Bool = LT+_ :: Int `compare` even _ :: Bool = LT+_ :: Int `compare` elem _ _ :: Bool = LT+_ :: Int `compare` e :: Char = GT+_ :: Int `compare` 'b' :: Char = LT+_ :: Int `compare` zs :: [Int] = LT+_ :: Int `compare` [0,0] :: [Int] = LT+_ :: Int `compare` [1] :: [Int] = LT+_ :: Int `compare` _:ys :: [Int] = LT+_ :: Int `compare` [_,0] :: [Int] = LT+_ :: Int `compare` _:_:xs :: [Int] = LT+_ :: Int `compare` [_,_] :: [Int] = LT+_ :: Int `compare` _:_:_:_ :: [Int] = LT+_ :: Int `compare` _:x:_ :: [Int] = LT+_ :: Int `compare` _:0:_ :: [Int] = LT+_ :: Int `compare` _:id _:_ :: [Int] = LT+_ :: Int `compare` _:tail _ :: [Int] = LT+_ :: Int `compare` _:(_ ++ _) :: [Int] = LT+_ :: Int `compare` x:xs :: [Int] = LT+_ :: Int `compare` [x] :: [Int] = LT+_ :: Int `compare` x:_:_ :: [Int] = LT+_ :: Int `compare` 0:xs :: [Int] = LT+_ :: Int `compare` [0] :: [Int] = LT+_ :: Int `compare` 0:_:_ :: [Int] = LT+_ :: Int `compare` id _:xs :: [Int] = LT+_ :: Int `compare` [id _] :: [Int] = LT+_ :: Int `compare` id _:_:_ :: [Int] = LT+_ :: Int `compare` y:_ :: [Int] = LT+_ :: Int `compare` 1:_ :: [Int] = LT+_ :: Int `compare` id x:_ :: [Int] = LT+_ :: Int `compare` id 0:_ :: [Int] = LT+_ :: Int `compare` id (id _):_ :: [Int] = LT+_ :: Int `compare` negate _:_ :: [Int] = LT+_ :: Int `compare` abs _:_ :: [Int] = LT+_ :: Int `compare` _ + _:_ :: [Int] = LT+_ :: Int `compare` head _:_ :: [Int] = LT+_ :: Int `compare` ord _:_ :: [Int] = LT+_ :: Int `compare` tail xs :: [Int] = LT+_ :: Int `compare` tail [] :: [Int] = LT+_ :: Int `compare` tail (_:_) :: [Int] = LT+_ :: Int `compare` _ ++ xs :: [Int] = LT+_ :: Int `compare` _ ++ [] :: [Int] = LT+_ :: Int `compare` _ ++ (_:_) :: [Int] = LT+_ :: Int `compare` xs ++ _ :: [Int] = LT+_ :: Int `compare` [] ++ _ :: [Int] = LT+_ :: Int `compare` (_:_) ++ _ :: [Int] = LT+_ :: Int `compare` sort _ :: [Int] = LT+_ :: Int `compare` insert _ _ :: [Int] = LT+_ :: Int `compare` (x +) :: Int -> Int = LT+_ :: Int `compare` (0 +) :: Int -> Int = LT+_ :: Int `compare` (id _ +) :: Int -> Int = LT+_ :: Int `compare` (_ *) :: Int -> Int = LT+_ :: Int `compare` f :: Int -> Int = LT+_ :: Int `compare` (_ ||) :: Bool -> Bool = LT+_ :: Int `compare` (&&) :: Bool -> Bool -> Bool = LT+x :: Int `compare` z :: Int = LT+x :: Int `compare` -1 :: Int = LT+x :: Int `compare` id y :: Int = LT+x :: Int `compare` id 1 :: Int = LT+x :: Int `compare` id (id x) :: Int = LT+x :: Int `compare` id (id 0) :: Int = LT+x :: Int `compare` id (id (id _)) :: Int = LT+x :: Int `compare` id (negate _) :: Int = LT+x :: Int `compare` id (abs _) :: Int = LT+x :: Int `compare` id (_ + _) :: Int = LT+x :: Int `compare` id (head _) :: Int = LT+x :: Int `compare` id (ord _) :: Int = LT+x :: Int `compare` negate x :: Int = LT+x :: Int `compare` negate 0 :: Int = LT+x :: Int `compare` negate (id _) :: Int = LT+x :: Int `compare` abs x :: Int = LT+x :: Int `compare` abs 0 :: Int = LT+x :: Int `compare` abs (id _) :: Int = LT+x :: Int `compare` _ + x :: Int = LT+x :: Int `compare` _ + 0 :: Int = LT+x :: Int `compare` _ + id _ :: Int = LT+x :: Int `compare` x + _ :: Int = LT+x :: Int `compare` 0 + _ :: Int = LT+x :: Int `compare` id _ + _ :: Int = LT+x :: Int `compare` _ * _ :: Int = LT+x :: Int `compare` f _ :: Int = LT+x :: Int `compare` head xs :: Int = LT+x :: Int `compare` head [] :: Int = LT+x :: Int `compare` head (_:_) :: Int = LT+x :: Int `compare` ord c :: Int = LT+x :: Int `compare` ord 'a' :: Int = LT+x :: Int `compare` q :: Bool = GT+x :: Int `compare` not p :: Bool = LT+x :: Int `compare` not False :: Bool = LT+x :: Int `compare` not True :: Bool = LT+x :: Int `compare` not (not _) :: Bool = LT+x :: Int `compare` _ || _ :: Bool = LT+x :: Int `compare` d :: Char = GT+x :: Int `compare` ' ' :: Char = LT+x :: Int `compare` ys :: [Int] = LT+x :: Int `compare` [0] :: [Int] = LT+x :: Int `compare` _:xs :: [Int] = LT+x :: Int `compare` [_] :: [Int] = LT+x :: Int `compare` _:_:_ :: [Int] = LT+x :: Int `compare` x:_ :: [Int] = LT+x :: Int `compare` 0:_ :: [Int] = LT+x :: Int `compare` id _:_ :: [Int] = LT+x :: Int `compare` tail _ :: [Int] = LT+x :: Int `compare` _ ++ _ :: [Int] = LT+x :: Int `compare` negate :: Int -> Int = LT+x :: Int `compare` abs :: Int -> Int = LT+x :: Int `compare` (_ +) :: Int -> Int = LT+x :: Int `compare` (*) :: Int -> Int -> Int = LT+x :: Int `compare` not :: Bool -> Bool = LT+x :: Int `compare` (||) :: Bool -> Bool -> Bool = LT+0 :: Int `compare` z :: Int = GT+0 :: Int `compare` -1 :: Int = GT+0 :: Int `compare` id y :: Int = LT+0 :: Int `compare` id 1 :: Int = LT+0 :: Int `compare` id (id x) :: Int = LT+0 :: Int `compare` id (id 0) :: Int = LT+0 :: Int `compare` id (id (id _)) :: Int = LT+0 :: Int `compare` id (negate _) :: Int = LT+0 :: Int `compare` id (abs _) :: Int = LT+0 :: Int `compare` id (_ + _) :: Int = LT+0 :: Int `compare` id (head _) :: Int = LT+0 :: Int `compare` id (ord _) :: Int = LT+0 :: Int `compare` negate x :: Int = LT+0 :: Int `compare` negate 0 :: Int = LT+0 :: Int `compare` negate (id _) :: Int = LT+0 :: Int `compare` abs x :: Int = LT+0 :: Int `compare` abs 0 :: Int = LT+0 :: Int `compare` abs (id _) :: Int = LT+0 :: Int `compare` _ + x :: Int = LT+0 :: Int `compare` _ + 0 :: Int = LT+0 :: Int `compare` _ + id _ :: Int = LT+0 :: Int `compare` x + _ :: Int = LT+0 :: Int `compare` 0 + _ :: Int = LT+0 :: Int `compare` id _ + _ :: Int = LT+0 :: Int `compare` _ * _ :: Int = LT+0 :: Int `compare` f _ :: Int = LT+0 :: Int `compare` head xs :: Int = LT+0 :: Int `compare` head [] :: Int = LT+0 :: Int `compare` head (_:_) :: Int = LT+0 :: Int `compare` ord c :: Int = LT+0 :: Int `compare` ord 'a' :: Int = LT+0 :: Int `compare` q :: Bool = GT+0 :: Int `compare` not p :: Bool = LT+0 :: Int `compare` not False :: Bool = LT+0 :: Int `compare` not True :: Bool = LT+0 :: Int `compare` not (not _) :: Bool = LT+0 :: Int `compare` _ || _ :: Bool = LT+0 :: Int `compare` d :: Char = GT+0 :: Int `compare` ' ' :: Char = GT+0 :: Int `compare` ys :: [Int] = GT+0 :: Int `compare` [0] :: [Int] = LT+0 :: Int `compare` _:xs :: [Int] = LT+0 :: Int `compare` [_] :: [Int] = LT+0 :: Int `compare` _:_:_ :: [Int] = LT+0 :: Int `compare` x:_ :: [Int] = LT+0 :: Int `compare` 0:_ :: [Int] = LT+0 :: Int `compare` id _:_ :: [Int] = LT+0 :: Int `compare` tail _ :: [Int] = LT+0 :: Int `compare` _ ++ _ :: [Int] = LT+0 :: Int `compare` negate :: Int -> Int = LT+0 :: Int `compare` abs :: Int -> Int = LT+0 :: Int `compare` (_ +) :: Int -> Int = LT+0 :: Int `compare` (*) :: Int -> Int -> Int = LT+0 :: Int `compare` not :: Bool -> Bool = LT+0 :: Int `compare` (||) :: Bool -> Bool -> Bool = LT+id _ :: Int `compare` z :: Int = GT+id _ :: Int `compare` -1 :: Int = GT+id _ :: Int `compare` id y :: Int = LT+id _ :: Int `compare` id 1 :: Int = LT+id _ :: Int `compare` id (id x) :: Int = LT+id _ :: Int `compare` id (id 0) :: Int = LT+id _ :: Int `compare` id (id (id _)) :: Int = LT+id _ :: Int `compare` id (negate _) :: Int = LT+id _ :: Int `compare` id (abs _) :: Int = LT+id _ :: Int `compare` id (_ + _) :: Int = LT+id _ :: Int `compare` id (head _) :: Int = LT+id _ :: Int `compare` id (ord _) :: Int = LT+id _ :: Int `compare` negate x :: Int = LT+id _ :: Int `compare` negate 0 :: Int = LT+id _ :: Int `compare` negate (id _) :: Int = LT+id _ :: Int `compare` abs x :: Int = GT+id _ :: Int `compare` abs 0 :: Int = LT+id _ :: Int `compare` abs (id _) :: Int = LT+id _ :: Int `compare` _ + x :: Int = LT+id _ :: Int `compare` _ + 0 :: Int = LT+id _ :: Int `compare` _ + id _ :: Int = LT+id _ :: Int `compare` x + _ :: Int = LT+id _ :: Int `compare` 0 + _ :: Int = LT+id _ :: Int `compare` id _ + _ :: Int = LT+id _ :: Int `compare` _ * _ :: Int = LT+id _ :: Int `compare` f _ :: Int = GT+id _ :: Int `compare` head xs :: Int = LT+id _ :: Int `compare` head [] :: Int = LT+id _ :: Int `compare` head (_:_) :: Int = LT+id _ :: Int `compare` ord c :: Int = GT+id _ :: Int `compare` ord 'a' :: Int = LT+id _ :: Int `compare` q :: Bool = GT+id _ :: Int `compare` not p :: Bool = GT+id _ :: Int `compare` not False :: Bool = LT+id _ :: Int `compare` not True :: Bool = LT+id _ :: Int `compare` not (not _) :: Bool = LT+id _ :: Int `compare` _ || _ :: Bool = LT+id _ :: Int `compare` d :: Char = GT+id _ :: Int `compare` ' ' :: Char = GT+id _ :: Int `compare` ys :: [Int] = GT+id _ :: Int `compare` [0] :: [Int] = GT+id _ :: Int `compare` _:xs :: [Int] = LT+id _ :: Int `compare` [_] :: [Int] = LT+id _ :: Int `compare` _:_:_ :: [Int] = LT+id _ :: Int `compare` x:_ :: [Int] = LT+id _ :: Int `compare` 0:_ :: [Int] = LT+id _ :: Int `compare` id _:_ :: [Int] = LT+id _ :: Int `compare` tail _ :: [Int] = LT+id _ :: Int `compare` _ ++ _ :: [Int] = LT+id _ :: Int `compare` negate :: Int -> Int = GT+id _ :: Int `compare` abs :: Int -> Int = GT+id _ :: Int `compare` (_ +) :: Int -> Int = LT+id _ :: Int `compare` (*) :: Int -> Int -> Int = GT+id _ :: Int `compare` not :: Bool -> Bool = GT+id _ :: Int `compare` (||) :: Bool -> Bool -> Bool = GT+_ :: Bool `compare` z :: Int = LT+_ :: Bool `compare` -1 :: Int = LT+_ :: Bool `compare` id y :: Int = LT+_ :: Bool `compare` id 1 :: Int = LT+_ :: Bool `compare` id (id x) :: Int = LT+_ :: Bool `compare` id (id 0) :: Int = LT+_ :: Bool `compare` id (id (id _)) :: Int = LT+_ :: Bool `compare` id (negate _) :: Int = LT+_ :: Bool `compare` id (abs _) :: Int = LT+_ :: Bool `compare` id (_ + _) :: Int = LT+_ :: Bool `compare` id (head _) :: Int = LT+_ :: Bool `compare` id (ord _) :: Int = LT+_ :: Bool `compare` negate x :: Int = LT+_ :: Bool `compare` negate 0 :: Int = LT+_ :: Bool `compare` negate (id _) :: Int = LT+_ :: Bool `compare` abs x :: Int = LT+_ :: Bool `compare` abs 0 :: Int = LT+_ :: Bool `compare` abs (id _) :: Int = LT+_ :: Bool `compare` _ + x :: Int = LT+_ :: Bool `compare` _ + 0 :: Int = LT+_ :: Bool `compare` _ + id _ :: Int = LT+_ :: Bool `compare` x + _ :: Int = LT+_ :: Bool `compare` 0 + _ :: Int = LT+_ :: Bool `compare` id _ + _ :: Int = LT+_ :: Bool `compare` _ * _ :: Int = LT+_ :: Bool `compare` f _ :: Int = LT+_ :: Bool `compare` head xs :: Int = LT+_ :: Bool `compare` head [] :: Int = LT+_ :: Bool `compare` head (_:_) :: Int = LT+_ :: Bool `compare` ord c :: Int = LT+_ :: Bool `compare` ord 'a' :: Int = LT+_ :: Bool `compare` q :: Bool = LT+_ :: Bool `compare` not p :: Bool = LT+_ :: Bool `compare` not False :: Bool = LT+_ :: Bool `compare` not True :: Bool = LT+_ :: Bool `compare` not (not _) :: Bool = LT+_ :: Bool `compare` _ || _ :: Bool = LT+_ :: Bool `compare` d :: Char = LT+_ :: Bool `compare` ' ' :: Char = LT+_ :: Bool `compare` ys :: [Int] = LT+_ :: Bool `compare` [0] :: [Int] = LT+_ :: Bool `compare` _:xs :: [Int] = LT+_ :: Bool `compare` [_] :: [Int] = LT+_ :: Bool `compare` _:_:_ :: [Int] = LT+_ :: Bool `compare` x:_ :: [Int] = LT+_ :: Bool `compare` 0:_ :: [Int] = LT+_ :: Bool `compare` id _:_ :: [Int] = LT+_ :: Bool `compare` tail _ :: [Int] = LT+_ :: Bool `compare` _ ++ _ :: [Int] = LT+_ :: Bool `compare` negate :: Int -> Int = LT+_ :: Bool `compare` abs :: Int -> Int = LT+_ :: Bool `compare` (_ +) :: Int -> Int = LT+_ :: Bool `compare` (*) :: Int -> Int -> Int = LT+_ :: Bool `compare` not :: Bool -> Bool = LT+_ :: Bool `compare` (||) :: Bool -> Bool -> Bool = LT+_ :: Char `compare` z :: Int = LT+_ :: Char `compare` -1 :: Int = LT+_ :: Char `compare` id y :: Int = LT+_ :: Char `compare` id 1 :: Int = LT+_ :: Char `compare` id (id x) :: Int = LT+_ :: Char `compare` id (id 0) :: Int = LT+_ :: Char `compare` id (id (id _)) :: Int = LT+_ :: Char `compare` id (negate _) :: Int = LT+_ :: Char `compare` id (abs _) :: Int = LT+_ :: Char `compare` id (_ + _) :: Int = LT+_ :: Char `compare` id (head _) :: Int = LT+_ :: Char `compare` id (ord _) :: Int = LT+_ :: Char `compare` negate x :: Int = LT+_ :: Char `compare` negate 0 :: Int = LT+_ :: Char `compare` negate (id _) :: Int = LT+_ :: Char `compare` abs x :: Int = LT+_ :: Char `compare` abs 0 :: Int = LT+_ :: Char `compare` abs (id _) :: Int = LT+_ :: Char `compare` _ + x :: Int = LT+_ :: Char `compare` _ + 0 :: Int = LT+_ :: Char `compare` _ + id _ :: Int = LT+_ :: Char `compare` x + _ :: Int = LT+_ :: Char `compare` 0 + _ :: Int = LT+_ :: Char `compare` id _ + _ :: Int = LT+_ :: Char `compare` _ * _ :: Int = LT+_ :: Char `compare` f _ :: Int = LT+_ :: Char `compare` head xs :: Int = LT+_ :: Char `compare` head [] :: Int = LT+_ :: Char `compare` head (_:_) :: Int = LT+_ :: Char `compare` ord c :: Int = LT+_ :: Char `compare` ord 'a' :: Int = LT+_ :: Char `compare` q :: Bool = GT+_ :: Char `compare` not p :: Bool = LT+_ :: Char `compare` not False :: Bool = LT+_ :: Char `compare` not True :: Bool = LT+_ :: Char `compare` not (not _) :: Bool = LT+_ :: Char `compare` _ || _ :: Bool = LT+_ :: Char `compare` d :: Char = LT+_ :: Char `compare` ' ' :: Char = LT+_ :: Char `compare` ys :: [Int] = LT+_ :: Char `compare` [0] :: [Int] = LT+_ :: Char `compare` _:xs :: [Int] = LT+_ :: Char `compare` [_] :: [Int] = LT+_ :: Char `compare` _:_:_ :: [Int] = LT+_ :: Char `compare` x:_ :: [Int] = LT+_ :: Char `compare` 0:_ :: [Int] = LT+_ :: Char `compare` id _:_ :: [Int] = LT+_ :: Char `compare` tail _ :: [Int] = LT+_ :: Char `compare` _ ++ _ :: [Int] = LT+_ :: Char `compare` negate :: Int -> Int = LT+_ :: Char `compare` abs :: Int -> Int = LT+_ :: Char `compare` (_ +) :: Int -> Int = LT+_ :: Char `compare` (*) :: Int -> Int -> Int = LT+_ :: Char `compare` not :: Bool -> Bool = LT+_ :: Char `compare` (||) :: Bool -> Bool -> Bool = LT+_ :: [Int] `compare` z :: Int = GT+_ :: [Int] `compare` -1 :: Int = LT+_ :: [Int] `compare` id y :: Int = LT+_ :: [Int] `compare` id 1 :: Int = LT+_ :: [Int] `compare` id (id x) :: Int = LT+_ :: [Int] `compare` id (id 0) :: Int = LT+_ :: [Int] `compare` id (id (id _)) :: Int = LT+_ :: [Int] `compare` id (negate _) :: Int = LT+_ :: [Int] `compare` id (abs _) :: Int = LT+_ :: [Int] `compare` id (_ + _) :: Int = LT+_ :: [Int] `compare` id (head _) :: Int = LT+_ :: [Int] `compare` id (ord _) :: Int = LT+_ :: [Int] `compare` negate x :: Int = LT+_ :: [Int] `compare` negate 0 :: Int = LT+_ :: [Int] `compare` negate (id _) :: Int = LT+_ :: [Int] `compare` abs x :: Int = LT+_ :: [Int] `compare` abs 0 :: Int = LT+_ :: [Int] `compare` abs (id _) :: Int = LT+_ :: [Int] `compare` _ + x :: Int = LT+_ :: [Int] `compare` _ + 0 :: Int = LT+_ :: [Int] `compare` _ + id _ :: Int = LT+_ :: [Int] `compare` x + _ :: Int = LT+_ :: [Int] `compare` 0 + _ :: Int = LT+_ :: [Int] `compare` id _ + _ :: Int = LT+_ :: [Int] `compare` _ * _ :: Int = LT+_ :: [Int] `compare` f _ :: Int = LT+_ :: [Int] `compare` head xs :: Int = LT+_ :: [Int] `compare` head [] :: Int = LT+_ :: [Int] `compare` head (_:_) :: Int = LT+_ :: [Int] `compare` ord c :: Int = LT+_ :: [Int] `compare` ord 'a' :: Int = LT+_ :: [Int] `compare` q :: Bool = GT+_ :: [Int] `compare` not p :: Bool = LT+_ :: [Int] `compare` not False :: Bool = LT+_ :: [Int] `compare` not True :: Bool = LT+_ :: [Int] `compare` not (not _) :: Bool = LT+_ :: [Int] `compare` _ || _ :: Bool = LT+_ :: [Int] `compare` d :: Char = GT+_ :: [Int] `compare` ' ' :: Char = LT+_ :: [Int] `compare` ys :: [Int] = LT+_ :: [Int] `compare` [0] :: [Int] = LT+_ :: [Int] `compare` _:xs :: [Int] = LT+_ :: [Int] `compare` [_] :: [Int] = LT+_ :: [Int] `compare` _:_:_ :: [Int] = LT+_ :: [Int] `compare` x:_ :: [Int] = LT+_ :: [Int] `compare` 0:_ :: [Int] = LT+_ :: [Int] `compare` id _:_ :: [Int] = LT+_ :: [Int] `compare` tail _ :: [Int] = LT+_ :: [Int] `compare` _ ++ _ :: [Int] = LT+_ :: [Int] `compare` negate :: Int -> Int = LT+_ :: [Int] `compare` abs :: Int -> Int = LT+_ :: [Int] `compare` (_ +) :: Int -> Int = LT+_ :: [Int] `compare` (*) :: Int -> Int -> Int = LT+_ :: [Int] `compare` not :: Bool -> Bool = LT+_ :: [Int] `compare` (||) :: Bool -> Bool -> Bool = LT+y :: Int `compare` y :: Int = EQ+y :: Int `compare` 1 :: Int = LT+y :: Int `compare` id x :: Int = LT+y :: Int `compare` id 0 :: Int = LT+y :: Int `compare` id (id _) :: Int = LT+y :: Int `compare` negate _ :: Int = LT+y :: Int `compare` abs _ :: Int = LT+y :: Int `compare` _ + _ :: Int = LT+y :: Int `compare` head _ :: Int = LT+y :: Int `compare` ord _ :: Int = LT+y :: Int `compare` p :: Bool = GT+y :: Int `compare` False :: Bool = LT+y :: Int `compare` True :: Bool = LT+y :: Int `compare` not _ :: Bool = LT+y :: Int `compare` c :: Char = GT+y :: Int `compare` 'a' :: Char = LT+y :: Int `compare` xs :: [Int] = LT+y :: Int `compare` [] :: [Int] = LT+y :: Int `compare` _:_ :: [Int] = LT+y :: Int `compare` id :: Int -> Int = LT+y :: Int `compare` (+) :: Int -> Int -> Int = LT+1 :: Int `compare` y :: Int = GT+1 :: Int `compare` 1 :: Int = EQ+1 :: Int `compare` id x :: Int = LT+1 :: Int `compare` id 0 :: Int = LT+1 :: Int `compare` id (id _) :: Int = LT+1 :: Int `compare` negate _ :: Int = LT+1 :: Int `compare` abs _ :: Int = LT+1 :: Int `compare` _ + _ :: Int = LT+1 :: Int `compare` head _ :: Int = LT+1 :: Int `compare` ord _ :: Int = LT+1 :: Int `compare` p :: Bool = GT+1 :: Int `compare` False :: Bool = GT+1 :: Int `compare` True :: Bool = GT+1 :: Int `compare` not _ :: Bool = LT+1 :: Int `compare` c :: Char = GT+1 :: Int `compare` 'a' :: Char = GT+1 :: Int `compare` xs :: [Int] = GT+1 :: Int `compare` [] :: [Int] = LT+1 :: Int `compare` _:_ :: [Int] = LT+
+ test/model/bench/pairs.out view
@@ -0,0 +1,1001 @@+(_ :: Int,_ :: Int)+(_ :: Int,x :: Int)+(_ :: Int,0 :: Int)+(_ :: Int,id _ :: Int)+(_ :: Int,_ :: Bool)+(_ :: Int,_ :: Char)+(_ :: Int,_ :: [Int])+(x :: Int,_ :: Int)+(0 :: Int,_ :: Int)+(id _ :: Int,_ :: Int)+(_ :: Bool,_ :: Int)+(_ :: Char,_ :: Int)+(_ :: [Int],_ :: Int)+(_ :: Int,y :: Int)+(_ :: Int,1 :: Int)+(_ :: Int,id x :: Int)+(_ :: Int,id 0 :: Int)+(_ :: Int,id (id _) :: Int)+(_ :: Int,negate _ :: Int)+(_ :: Int,abs _ :: Int)+(_ :: Int,_ + _ :: Int)+(_ :: Int,head _ :: Int)+(_ :: Int,ord _ :: Int)+(_ :: Int,p :: Bool)+(_ :: Int,False :: Bool)+(_ :: Int,True :: Bool)+(_ :: Int,not _ :: Bool)+(_ :: Int,c :: Char)+(_ :: Int,'a' :: Char)+(_ :: Int,xs :: [Int])+(_ :: Int,[] :: [Int])+(_ :: Int,_:_ :: [Int])+(_ :: Int,id :: Int -> Int)+(_ :: Int,(+) :: Int -> Int -> Int)+(x :: Int,x :: Int)+(x :: Int,0 :: Int)+(x :: Int,id _ :: Int)+(x :: Int,_ :: Bool)+(x :: Int,_ :: Char)+(x :: Int,_ :: [Int])+(0 :: Int,x :: Int)+(0 :: Int,0 :: Int)+(0 :: Int,id _ :: Int)+(0 :: Int,_ :: Bool)+(0 :: Int,_ :: Char)+(0 :: Int,_ :: [Int])+(id _ :: Int,x :: Int)+(id _ :: Int,0 :: Int)+(id _ :: Int,id _ :: Int)+(id _ :: Int,_ :: Bool)+(id _ :: Int,_ :: Char)+(id _ :: Int,_ :: [Int])+(_ :: Bool,x :: Int)+(_ :: Bool,0 :: Int)+(_ :: Bool,id _ :: Int)+(_ :: Bool,_ :: Bool)+(_ :: Bool,_ :: Char)+(_ :: Bool,_ :: [Int])+(_ :: Char,x :: Int)+(_ :: Char,0 :: Int)+(_ :: Char,id _ :: Int)+(_ :: Char,_ :: Bool)+(_ :: Char,_ :: Char)+(_ :: Char,_ :: [Int])+(_ :: [Int],x :: Int)+(_ :: [Int],0 :: Int)+(_ :: [Int],id _ :: Int)+(_ :: [Int],_ :: Bool)+(_ :: [Int],_ :: Char)+(_ :: [Int],_ :: [Int])+(y :: Int,_ :: Int)+(1 :: Int,_ :: Int)+(id x :: Int,_ :: Int)+(id 0 :: Int,_ :: Int)+(id (id _) :: Int,_ :: Int)+(negate _ :: Int,_ :: Int)+(abs _ :: Int,_ :: Int)+(_ + _ :: Int,_ :: Int)+(head _ :: Int,_ :: Int)+(ord _ :: Int,_ :: Int)+(p :: Bool,_ :: Int)+(False :: Bool,_ :: Int)+(True :: Bool,_ :: Int)+(not _ :: Bool,_ :: Int)+(c :: Char,_ :: Int)+('a' :: Char,_ :: Int)+(xs :: [Int],_ :: Int)+([] :: [Int],_ :: Int)+(_:_ :: [Int],_ :: Int)+(id :: Int -> Int,_ :: Int)+((+) :: Int -> Int -> Int,_ :: Int)+(_ :: Int,z :: Int)+(_ :: Int,-1 :: Int)+(_ :: Int,id y :: Int)+(_ :: Int,id 1 :: Int)+(_ :: Int,id (id x) :: Int)+(_ :: Int,id (id 0) :: Int)+(_ :: Int,id (id (id _)) :: Int)+(_ :: Int,id (negate _) :: Int)+(_ :: Int,id (abs _) :: Int)+(_ :: Int,id (_ + _) :: Int)+(_ :: Int,id (head _) :: Int)+(_ :: Int,id (ord _) :: Int)+(_ :: Int,negate x :: Int)+(_ :: Int,negate 0 :: Int)+(_ :: Int,negate (id _) :: Int)+(_ :: Int,abs x :: Int)+(_ :: Int,abs 0 :: Int)+(_ :: Int,abs (id _) :: Int)+(_ :: Int,_ + x :: Int)+(_ :: Int,_ + 0 :: Int)+(_ :: Int,_ + id _ :: Int)+(_ :: Int,x + _ :: Int)+(_ :: Int,0 + _ :: Int)+(_ :: Int,id _ + _ :: Int)+(_ :: Int,_ * _ :: Int)+(_ :: Int,f _ :: Int)+(_ :: Int,head xs :: Int)+(_ :: Int,head [] :: Int)+(_ :: Int,head (_:_) :: Int)+(_ :: Int,ord c :: Int)+(_ :: Int,ord 'a' :: Int)+(_ :: Int,q :: Bool)+(_ :: Int,not p :: Bool)+(_ :: Int,not False :: Bool)+(_ :: Int,not True :: Bool)+(_ :: Int,not (not _) :: Bool)+(_ :: Int,_ || _ :: Bool)+(_ :: Int,d :: Char)+(_ :: Int,' ' :: Char)+(_ :: Int,ys :: [Int])+(_ :: Int,[0] :: [Int])+(_ :: Int,_:xs :: [Int])+(_ :: Int,[_] :: [Int])+(_ :: Int,_:_:_ :: [Int])+(_ :: Int,x:_ :: [Int])+(_ :: Int,0:_ :: [Int])+(_ :: Int,id _:_ :: [Int])+(_ :: Int,tail _ :: [Int])+(_ :: Int,_ ++ _ :: [Int])+(_ :: Int,negate :: Int -> Int)+(_ :: Int,abs :: Int -> Int)+(_ :: Int,(_ +) :: Int -> Int)+(_ :: Int,(*) :: Int -> Int -> Int)+(_ :: Int,not :: Bool -> Bool)+(_ :: Int,(||) :: Bool -> Bool -> Bool)+(x :: Int,y :: Int)+(x :: Int,1 :: Int)+(x :: Int,id x :: Int)+(x :: Int,id 0 :: Int)+(x :: Int,id (id _) :: Int)+(x :: Int,negate _ :: Int)+(x :: Int,abs _ :: Int)+(x :: Int,_ + _ :: Int)+(x :: Int,head _ :: Int)+(x :: Int,ord _ :: Int)+(x :: Int,p :: Bool)+(x :: Int,False :: Bool)+(x :: Int,True :: Bool)+(x :: Int,not _ :: Bool)+(x :: Int,c :: Char)+(x :: Int,'a' :: Char)+(x :: Int,xs :: [Int])+(x :: Int,[] :: [Int])+(x :: Int,_:_ :: [Int])+(x :: Int,id :: Int -> Int)+(x :: Int,(+) :: Int -> Int -> Int)+(0 :: Int,y :: Int)+(0 :: Int,1 :: Int)+(0 :: Int,id x :: Int)+(0 :: Int,id 0 :: Int)+(0 :: Int,id (id _) :: Int)+(0 :: Int,negate _ :: Int)+(0 :: Int,abs _ :: Int)+(0 :: Int,_ + _ :: Int)+(0 :: Int,head _ :: Int)+(0 :: Int,ord _ :: Int)+(0 :: Int,p :: Bool)+(0 :: Int,False :: Bool)+(0 :: Int,True :: Bool)+(0 :: Int,not _ :: Bool)+(0 :: Int,c :: Char)+(0 :: Int,'a' :: Char)+(0 :: Int,xs :: [Int])+(0 :: Int,[] :: [Int])+(0 :: Int,_:_ :: [Int])+(0 :: Int,id :: Int -> Int)+(0 :: Int,(+) :: Int -> Int -> Int)+(id _ :: Int,y :: Int)+(id _ :: Int,1 :: Int)+(id _ :: Int,id x :: Int)+(id _ :: Int,id 0 :: Int)+(id _ :: Int,id (id _) :: Int)+(id _ :: Int,negate _ :: Int)+(id _ :: Int,abs _ :: Int)+(id _ :: Int,_ + _ :: Int)+(id _ :: Int,head _ :: Int)+(id _ :: Int,ord _ :: Int)+(id _ :: Int,p :: Bool)+(id _ :: Int,False :: Bool)+(id _ :: Int,True :: Bool)+(id _ :: Int,not _ :: Bool)+(id _ :: Int,c :: Char)+(id _ :: Int,'a' :: Char)+(id _ :: Int,xs :: [Int])+(id _ :: Int,[] :: [Int])+(id _ :: Int,_:_ :: [Int])+(id _ :: Int,id :: Int -> Int)+(id _ :: Int,(+) :: Int -> Int -> Int)+(_ :: Bool,y :: Int)+(_ :: Bool,1 :: Int)+(_ :: Bool,id x :: Int)+(_ :: Bool,id 0 :: Int)+(_ :: Bool,id (id _) :: Int)+(_ :: Bool,negate _ :: Int)+(_ :: Bool,abs _ :: Int)+(_ :: Bool,_ + _ :: Int)+(_ :: Bool,head _ :: Int)+(_ :: Bool,ord _ :: Int)+(_ :: Bool,p :: Bool)+(_ :: Bool,False :: Bool)+(_ :: Bool,True :: Bool)+(_ :: Bool,not _ :: Bool)+(_ :: Bool,c :: Char)+(_ :: Bool,'a' :: Char)+(_ :: Bool,xs :: [Int])+(_ :: Bool,[] :: [Int])+(_ :: Bool,_:_ :: [Int])+(_ :: Bool,id :: Int -> Int)+(_ :: Bool,(+) :: Int -> Int -> Int)+(_ :: Char,y :: Int)+(_ :: Char,1 :: Int)+(_ :: Char,id x :: Int)+(_ :: Char,id 0 :: Int)+(_ :: Char,id (id _) :: Int)+(_ :: Char,negate _ :: Int)+(_ :: Char,abs _ :: Int)+(_ :: Char,_ + _ :: Int)+(_ :: Char,head _ :: Int)+(_ :: Char,ord _ :: Int)+(_ :: Char,p :: Bool)+(_ :: Char,False :: Bool)+(_ :: Char,True :: Bool)+(_ :: Char,not _ :: Bool)+(_ :: Char,c :: Char)+(_ :: Char,'a' :: Char)+(_ :: Char,xs :: [Int])+(_ :: Char,[] :: [Int])+(_ :: Char,_:_ :: [Int])+(_ :: Char,id :: Int -> Int)+(_ :: Char,(+) :: Int -> Int -> Int)+(_ :: [Int],y :: Int)+(_ :: [Int],1 :: Int)+(_ :: [Int],id x :: Int)+(_ :: [Int],id 0 :: Int)+(_ :: [Int],id (id _) :: Int)+(_ :: [Int],negate _ :: Int)+(_ :: [Int],abs _ :: Int)+(_ :: [Int],_ + _ :: Int)+(_ :: [Int],head _ :: Int)+(_ :: [Int],ord _ :: Int)+(_ :: [Int],p :: Bool)+(_ :: [Int],False :: Bool)+(_ :: [Int],True :: Bool)+(_ :: [Int],not _ :: Bool)+(_ :: [Int],c :: Char)+(_ :: [Int],'a' :: Char)+(_ :: [Int],xs :: [Int])+(_ :: [Int],[] :: [Int])+(_ :: [Int],_:_ :: [Int])+(_ :: [Int],id :: Int -> Int)+(_ :: [Int],(+) :: Int -> Int -> Int)+(y :: Int,x :: Int)+(y :: Int,0 :: Int)+(y :: Int,id _ :: Int)+(y :: Int,_ :: Bool)+(y :: Int,_ :: Char)+(y :: Int,_ :: [Int])+(1 :: Int,x :: Int)+(1 :: Int,0 :: Int)+(1 :: Int,id _ :: Int)+(1 :: Int,_ :: Bool)+(1 :: Int,_ :: Char)+(1 :: Int,_ :: [Int])+(id x :: Int,x :: Int)+(id x :: Int,0 :: Int)+(id x :: Int,id _ :: Int)+(id x :: Int,_ :: Bool)+(id x :: Int,_ :: Char)+(id x :: Int,_ :: [Int])+(id 0 :: Int,x :: Int)+(id 0 :: Int,0 :: Int)+(id 0 :: Int,id _ :: Int)+(id 0 :: Int,_ :: Bool)+(id 0 :: Int,_ :: Char)+(id 0 :: Int,_ :: [Int])+(id (id _) :: Int,x :: Int)+(id (id _) :: Int,0 :: Int)+(id (id _) :: Int,id _ :: Int)+(id (id _) :: Int,_ :: Bool)+(id (id _) :: Int,_ :: Char)+(id (id _) :: Int,_ :: [Int])+(negate _ :: Int,x :: Int)+(negate _ :: Int,0 :: Int)+(negate _ :: Int,id _ :: Int)+(negate _ :: Int,_ :: Bool)+(negate _ :: Int,_ :: Char)+(negate _ :: Int,_ :: [Int])+(abs _ :: Int,x :: Int)+(abs _ :: Int,0 :: Int)+(abs _ :: Int,id _ :: Int)+(abs _ :: Int,_ :: Bool)+(abs _ :: Int,_ :: Char)+(abs _ :: Int,_ :: [Int])+(_ + _ :: Int,x :: Int)+(_ + _ :: Int,0 :: Int)+(_ + _ :: Int,id _ :: Int)+(_ + _ :: Int,_ :: Bool)+(_ + _ :: Int,_ :: Char)+(_ + _ :: Int,_ :: [Int])+(head _ :: Int,x :: Int)+(head _ :: Int,0 :: Int)+(head _ :: Int,id _ :: Int)+(head _ :: Int,_ :: Bool)+(head _ :: Int,_ :: Char)+(head _ :: Int,_ :: [Int])+(ord _ :: Int,x :: Int)+(ord _ :: Int,0 :: Int)+(ord _ :: Int,id _ :: Int)+(ord _ :: Int,_ :: Bool)+(ord _ :: Int,_ :: Char)+(ord _ :: Int,_ :: [Int])+(p :: Bool,x :: Int)+(p :: Bool,0 :: Int)+(p :: Bool,id _ :: Int)+(p :: Bool,_ :: Bool)+(p :: Bool,_ :: Char)+(p :: Bool,_ :: [Int])+(False :: Bool,x :: Int)+(False :: Bool,0 :: Int)+(False :: Bool,id _ :: Int)+(False :: Bool,_ :: Bool)+(False :: Bool,_ :: Char)+(False :: Bool,_ :: [Int])+(True :: Bool,x :: Int)+(True :: Bool,0 :: Int)+(True :: Bool,id _ :: Int)+(True :: Bool,_ :: Bool)+(True :: Bool,_ :: Char)+(True :: Bool,_ :: [Int])+(not _ :: Bool,x :: Int)+(not _ :: Bool,0 :: Int)+(not _ :: Bool,id _ :: Int)+(not _ :: Bool,_ :: Bool)+(not _ :: Bool,_ :: Char)+(not _ :: Bool,_ :: [Int])+(c :: Char,x :: Int)+(c :: Char,0 :: Int)+(c :: Char,id _ :: Int)+(c :: Char,_ :: Bool)+(c :: Char,_ :: Char)+(c :: Char,_ :: [Int])+('a' :: Char,x :: Int)+('a' :: Char,0 :: Int)+('a' :: Char,id _ :: Int)+('a' :: Char,_ :: Bool)+('a' :: Char,_ :: Char)+('a' :: Char,_ :: [Int])+(xs :: [Int],x :: Int)+(xs :: [Int],0 :: Int)+(xs :: [Int],id _ :: Int)+(xs :: [Int],_ :: Bool)+(xs :: [Int],_ :: Char)+(xs :: [Int],_ :: [Int])+([] :: [Int],x :: Int)+([] :: [Int],0 :: Int)+([] :: [Int],id _ :: Int)+([] :: [Int],_ :: Bool)+([] :: [Int],_ :: Char)+([] :: [Int],_ :: [Int])+(_:_ :: [Int],x :: Int)+(_:_ :: [Int],0 :: Int)+(_:_ :: [Int],id _ :: Int)+(_:_ :: [Int],_ :: Bool)+(_:_ :: [Int],_ :: Char)+(_:_ :: [Int],_ :: [Int])+(id :: Int -> Int,x :: Int)+(id :: Int -> Int,0 :: Int)+(id :: Int -> Int,id _ :: Int)+(id :: Int -> Int,_ :: Bool)+(id :: Int -> Int,_ :: Char)+(id :: Int -> Int,_ :: [Int])+((+) :: Int -> Int -> Int,x :: Int)+((+) :: Int -> Int -> Int,0 :: Int)+((+) :: Int -> Int -> Int,id _ :: Int)+((+) :: Int -> Int -> Int,_ :: Bool)+((+) :: Int -> Int -> Int,_ :: Char)+((+) :: Int -> Int -> Int,_ :: [Int])+(z :: Int,_ :: Int)+(-1 :: Int,_ :: Int)+(id y :: Int,_ :: Int)+(id 1 :: Int,_ :: Int)+(id (id x) :: Int,_ :: Int)+(id (id 0) :: Int,_ :: Int)+(id (id (id _)) :: Int,_ :: Int)+(id (negate _) :: Int,_ :: Int)+(id (abs _) :: Int,_ :: Int)+(id (_ + _) :: Int,_ :: Int)+(id (head _) :: Int,_ :: Int)+(id (ord _) :: Int,_ :: Int)+(negate x :: Int,_ :: Int)+(negate 0 :: Int,_ :: Int)+(negate (id _) :: Int,_ :: Int)+(abs x :: Int,_ :: Int)+(abs 0 :: Int,_ :: Int)+(abs (id _) :: Int,_ :: Int)+(_ + x :: Int,_ :: Int)+(_ + 0 :: Int,_ :: Int)+(_ + id _ :: Int,_ :: Int)+(x + _ :: Int,_ :: Int)+(0 + _ :: Int,_ :: Int)+(id _ + _ :: Int,_ :: Int)+(_ * _ :: Int,_ :: Int)+(f _ :: Int,_ :: Int)+(head xs :: Int,_ :: Int)+(head [] :: Int,_ :: Int)+(head (_:_) :: Int,_ :: Int)+(ord c :: Int,_ :: Int)+(ord 'a' :: Int,_ :: Int)+(q :: Bool,_ :: Int)+(not p :: Bool,_ :: Int)+(not False :: Bool,_ :: Int)+(not True :: Bool,_ :: Int)+(not (not _) :: Bool,_ :: Int)+(_ || _ :: Bool,_ :: Int)+(d :: Char,_ :: Int)+(' ' :: Char,_ :: Int)+(ys :: [Int],_ :: Int)+([0] :: [Int],_ :: Int)+(_:xs :: [Int],_ :: Int)+([_] :: [Int],_ :: Int)+(_:_:_ :: [Int],_ :: Int)+(x:_ :: [Int],_ :: Int)+(0:_ :: [Int],_ :: Int)+(id _:_ :: [Int],_ :: Int)+(tail _ :: [Int],_ :: Int)+(_ ++ _ :: [Int],_ :: Int)+(negate :: Int -> Int,_ :: Int)+(abs :: Int -> Int,_ :: Int)+((_ +) :: Int -> Int,_ :: Int)+((*) :: Int -> Int -> Int,_ :: Int)+(not :: Bool -> Bool,_ :: Int)+((||) :: Bool -> Bool -> Bool,_ :: Int)+(_ :: Int,x' :: Int)+(_ :: Int,2 :: Int)+(_ :: Int,id z :: Int)+(_ :: Int,id (-1) :: Int)+(_ :: Int,id (id y) :: Int)+(_ :: Int,id (id 1) :: Int)+(_ :: Int,id (id (id x)) :: Int)+(_ :: Int,id (id (id 0)) :: Int)+(_ :: Int,id (id (id (id _))) :: Int)+(_ :: Int,id (id (negate _)) :: Int)+(_ :: Int,id (id (abs _)) :: Int)+(_ :: Int,id (id (_ + _)) :: Int)+(_ :: Int,id (id (head _)) :: Int)+(_ :: Int,id (id (ord _)) :: Int)+(_ :: Int,id (negate x) :: Int)+(_ :: Int,id (negate 0) :: Int)+(_ :: Int,id (negate (id _)) :: Int)+(_ :: Int,id (abs x) :: Int)+(_ :: Int,id (abs 0) :: Int)+(_ :: Int,id (abs (id _)) :: Int)+(_ :: Int,id (_ + x) :: Int)+(_ :: Int,id (_ + 0) :: Int)+(_ :: Int,id (_ + id _) :: Int)+(_ :: Int,id (x + _) :: Int)+(_ :: Int,id (0 + _) :: Int)+(_ :: Int,id (id _ + _) :: Int)+(_ :: Int,id (_ * _) :: Int)+(_ :: Int,id (f _) :: Int)+(_ :: Int,id (head xs) :: Int)+(_ :: Int,id (head []) :: Int)+(_ :: Int,id (head (_:_)) :: Int)+(_ :: Int,id (ord c) :: Int)+(_ :: Int,id (ord 'a') :: Int)+(_ :: Int,negate y :: Int)+(_ :: Int,negate 1 :: Int)+(_ :: Int,negate (id x) :: Int)+(_ :: Int,negate (id 0) :: Int)+(_ :: Int,negate (id (id _)) :: Int)+(_ :: Int,negate (negate _) :: Int)+(_ :: Int,negate (abs _) :: Int)+(_ :: Int,negate (_ + _) :: Int)+(_ :: Int,negate (head _) :: Int)+(_ :: Int,negate (ord _) :: Int)+(_ :: Int,abs y :: Int)+(_ :: Int,abs 1 :: Int)+(_ :: Int,abs (id x) :: Int)+(_ :: Int,abs (id 0) :: Int)+(_ :: Int,abs (id (id _)) :: Int)+(_ :: Int,abs (negate _) :: Int)+(_ :: Int,abs (abs _) :: Int)+(_ :: Int,abs (_ + _) :: Int)+(_ :: Int,abs (head _) :: Int)+(_ :: Int,abs (ord _) :: Int)+(_ :: Int,_ + y :: Int)+(_ :: Int,_ + 1 :: Int)+(_ :: Int,_ + id x :: Int)+(_ :: Int,_ + id 0 :: Int)+(_ :: Int,_ + id (id _) :: Int)+(_ :: Int,_ + negate _ :: Int)+(_ :: Int,_ + abs _ :: Int)+(_ :: Int,_ + (_ + _) :: Int)+(_ :: Int,_ + head _ :: Int)+(_ :: Int,_ + ord _ :: Int)+(_ :: Int,x + x :: Int)+(_ :: Int,x + 0 :: Int)+(_ :: Int,x + id _ :: Int)+(_ :: Int,0 + x :: Int)+(_ :: Int,0 + 0 :: Int)+(_ :: Int,0 + id _ :: Int)+(_ :: Int,id _ + x :: Int)+(_ :: Int,id _ + 0 :: Int)+(_ :: Int,id _ + id _ :: Int)+(_ :: Int,_ * x :: Int)+(_ :: Int,_ * 0 :: Int)+(_ :: Int,_ * id _ :: Int)+(_ :: Int,f x :: Int)+(_ :: Int,f 0 :: Int)+(_ :: Int,f (id _) :: Int)+(_ :: Int,y + _ :: Int)+(_ :: Int,1 + _ :: Int)+(_ :: Int,id x + _ :: Int)+(_ :: Int,id 0 + _ :: Int)+(_ :: Int,id (id _) + _ :: Int)+(_ :: Int,negate _ + _ :: Int)+(_ :: Int,abs _ + _ :: Int)+(_ :: Int,(_ + _) + _ :: Int)+(_ :: Int,head _ + _ :: Int)+(_ :: Int,ord _ + _ :: Int)+(_ :: Int,x * _ :: Int)+(_ :: Int,0 * _ :: Int)+(_ :: Int,id _ * _ :: Int)+(_ :: Int,g _ :: Int)+(_ :: Int,head ys :: Int)+(_ :: Int,head [0] :: Int)+(_ :: Int,head (_:xs) :: Int)+(_ :: Int,head [_] :: Int)+(_ :: Int,head (_:_:_) :: Int)+(_ :: Int,head (x:_) :: Int)+(_ :: Int,head (0:_) :: Int)+(_ :: Int,head (id _:_) :: Int)+(_ :: Int,head (tail _) :: Int)+(_ :: Int,head (_ ++ _) :: Int)+(_ :: Int,ord d :: Int)+(_ :: Int,ord ' ' :: Int)+(_ :: Int,r :: Bool)+(_ :: Int,not q :: Bool)+(_ :: Int,not (not p) :: Bool)+(_ :: Int,not (not False) :: Bool)+(_ :: Int,not (not True) :: Bool)+(_ :: Int,not (not (not _)) :: Bool)+(_ :: Int,not (_ || _) :: Bool)+(_ :: Int,_ || p :: Bool)+(_ :: Int,_ || False :: Bool)+(_ :: Int,_ || True :: Bool)+(_ :: Int,_ || not _ :: Bool)+(_ :: Int,p || _ :: Bool)+(_ :: Int,False || _ :: Bool)+(_ :: Int,True || _ :: Bool)+(_ :: Int,not _ || _ :: Bool)+(_ :: Int,_ && _ :: Bool)+(_ :: Int,_ == _ :: Bool)+(_ :: Int,_ == _ :: Bool)+(_ :: Int,odd _ :: Bool)+(_ :: Int,even _ :: Bool)+(_ :: Int,elem _ _ :: Bool)+(_ :: Int,e :: Char)+(_ :: Int,'b' :: Char)+(_ :: Int,zs :: [Int])+(_ :: Int,[0,0] :: [Int])+(_ :: Int,[1] :: [Int])+(_ :: Int,_:ys :: [Int])+(_ :: Int,[_,0] :: [Int])+(_ :: Int,_:_:xs :: [Int])+(_ :: Int,[_,_] :: [Int])+(_ :: Int,_:_:_:_ :: [Int])+(_ :: Int,_:x:_ :: [Int])+(_ :: Int,_:0:_ :: [Int])+(_ :: Int,_:id _:_ :: [Int])+(_ :: Int,_:tail _ :: [Int])+(_ :: Int,_:(_ ++ _) :: [Int])+(_ :: Int,x:xs :: [Int])+(_ :: Int,[x] :: [Int])+(_ :: Int,x:_:_ :: [Int])+(_ :: Int,0:xs :: [Int])+(_ :: Int,[0] :: [Int])+(_ :: Int,0:_:_ :: [Int])+(_ :: Int,id _:xs :: [Int])+(_ :: Int,[id _] :: [Int])+(_ :: Int,id _:_:_ :: [Int])+(_ :: Int,y:_ :: [Int])+(_ :: Int,1:_ :: [Int])+(_ :: Int,id x:_ :: [Int])+(_ :: Int,id 0:_ :: [Int])+(_ :: Int,id (id _):_ :: [Int])+(_ :: Int,negate _:_ :: [Int])+(_ :: Int,abs _:_ :: [Int])+(_ :: Int,_ + _:_ :: [Int])+(_ :: Int,head _:_ :: [Int])+(_ :: Int,ord _:_ :: [Int])+(_ :: Int,tail xs :: [Int])+(_ :: Int,tail [] :: [Int])+(_ :: Int,tail (_:_) :: [Int])+(_ :: Int,_ ++ xs :: [Int])+(_ :: Int,_ ++ [] :: [Int])+(_ :: Int,_ ++ (_:_) :: [Int])+(_ :: Int,xs ++ _ :: [Int])+(_ :: Int,[] ++ _ :: [Int])+(_ :: Int,(_:_) ++ _ :: [Int])+(_ :: Int,sort _ :: [Int])+(_ :: Int,insert _ _ :: [Int])+(_ :: Int,(x +) :: Int -> Int)+(_ :: Int,(0 +) :: Int -> Int)+(_ :: Int,(id _ +) :: Int -> Int)+(_ :: Int,(_ *) :: Int -> Int)+(_ :: Int,f :: Int -> Int)+(_ :: Int,(_ ||) :: Bool -> Bool)+(_ :: Int,(&&) :: Bool -> Bool -> Bool)+(x :: Int,z :: Int)+(x :: Int,-1 :: Int)+(x :: Int,id y :: Int)+(x :: Int,id 1 :: Int)+(x :: Int,id (id x) :: Int)+(x :: Int,id (id 0) :: Int)+(x :: Int,id (id (id _)) :: Int)+(x :: Int,id (negate _) :: Int)+(x :: Int,id (abs _) :: Int)+(x :: Int,id (_ + _) :: Int)+(x :: Int,id (head _) :: Int)+(x :: Int,id (ord _) :: Int)+(x :: Int,negate x :: Int)+(x :: Int,negate 0 :: Int)+(x :: Int,negate (id _) :: Int)+(x :: Int,abs x :: Int)+(x :: Int,abs 0 :: Int)+(x :: Int,abs (id _) :: Int)+(x :: Int,_ + x :: Int)+(x :: Int,_ + 0 :: Int)+(x :: Int,_ + id _ :: Int)+(x :: Int,x + _ :: Int)+(x :: Int,0 + _ :: Int)+(x :: Int,id _ + _ :: Int)+(x :: Int,_ * _ :: Int)+(x :: Int,f _ :: Int)+(x :: Int,head xs :: Int)+(x :: Int,head [] :: Int)+(x :: Int,head (_:_) :: Int)+(x :: Int,ord c :: Int)+(x :: Int,ord 'a' :: Int)+(x :: Int,q :: Bool)+(x :: Int,not p :: Bool)+(x :: Int,not False :: Bool)+(x :: Int,not True :: Bool)+(x :: Int,not (not _) :: Bool)+(x :: Int,_ || _ :: Bool)+(x :: Int,d :: Char)+(x :: Int,' ' :: Char)+(x :: Int,ys :: [Int])+(x :: Int,[0] :: [Int])+(x :: Int,_:xs :: [Int])+(x :: Int,[_] :: [Int])+(x :: Int,_:_:_ :: [Int])+(x :: Int,x:_ :: [Int])+(x :: Int,0:_ :: [Int])+(x :: Int,id _:_ :: [Int])+(x :: Int,tail _ :: [Int])+(x :: Int,_ ++ _ :: [Int])+(x :: Int,negate :: Int -> Int)+(x :: Int,abs :: Int -> Int)+(x :: Int,(_ +) :: Int -> Int)+(x :: Int,(*) :: Int -> Int -> Int)+(x :: Int,not :: Bool -> Bool)+(x :: Int,(||) :: Bool -> Bool -> Bool)+(0 :: Int,z :: Int)+(0 :: Int,-1 :: Int)+(0 :: Int,id y :: Int)+(0 :: Int,id 1 :: Int)+(0 :: Int,id (id x) :: Int)+(0 :: Int,id (id 0) :: Int)+(0 :: Int,id (id (id _)) :: Int)+(0 :: Int,id (negate _) :: Int)+(0 :: Int,id (abs _) :: Int)+(0 :: Int,id (_ + _) :: Int)+(0 :: Int,id (head _) :: Int)+(0 :: Int,id (ord _) :: Int)+(0 :: Int,negate x :: Int)+(0 :: Int,negate 0 :: Int)+(0 :: Int,negate (id _) :: Int)+(0 :: Int,abs x :: Int)+(0 :: Int,abs 0 :: Int)+(0 :: Int,abs (id _) :: Int)+(0 :: Int,_ + x :: Int)+(0 :: Int,_ + 0 :: Int)+(0 :: Int,_ + id _ :: Int)+(0 :: Int,x + _ :: Int)+(0 :: Int,0 + _ :: Int)+(0 :: Int,id _ + _ :: Int)+(0 :: Int,_ * _ :: Int)+(0 :: Int,f _ :: Int)+(0 :: Int,head xs :: Int)+(0 :: Int,head [] :: Int)+(0 :: Int,head (_:_) :: Int)+(0 :: Int,ord c :: Int)+(0 :: Int,ord 'a' :: Int)+(0 :: Int,q :: Bool)+(0 :: Int,not p :: Bool)+(0 :: Int,not False :: Bool)+(0 :: Int,not True :: Bool)+(0 :: Int,not (not _) :: Bool)+(0 :: Int,_ || _ :: Bool)+(0 :: Int,d :: Char)+(0 :: Int,' ' :: Char)+(0 :: Int,ys :: [Int])+(0 :: Int,[0] :: [Int])+(0 :: Int,_:xs :: [Int])+(0 :: Int,[_] :: [Int])+(0 :: Int,_:_:_ :: [Int])+(0 :: Int,x:_ :: [Int])+(0 :: Int,0:_ :: [Int])+(0 :: Int,id _:_ :: [Int])+(0 :: Int,tail _ :: [Int])+(0 :: Int,_ ++ _ :: [Int])+(0 :: Int,negate :: Int -> Int)+(0 :: Int,abs :: Int -> Int)+(0 :: Int,(_ +) :: Int -> Int)+(0 :: Int,(*) :: Int -> Int -> Int)+(0 :: Int,not :: Bool -> Bool)+(0 :: Int,(||) :: Bool -> Bool -> Bool)+(id _ :: Int,z :: Int)+(id _ :: Int,-1 :: Int)+(id _ :: Int,id y :: Int)+(id _ :: Int,id 1 :: Int)+(id _ :: Int,id (id x) :: Int)+(id _ :: Int,id (id 0) :: Int)+(id _ :: Int,id (id (id _)) :: Int)+(id _ :: Int,id (negate _) :: Int)+(id _ :: Int,id (abs _) :: Int)+(id _ :: Int,id (_ + _) :: Int)+(id _ :: Int,id (head _) :: Int)+(id _ :: Int,id (ord _) :: Int)+(id _ :: Int,negate x :: Int)+(id _ :: Int,negate 0 :: Int)+(id _ :: Int,negate (id _) :: Int)+(id _ :: Int,abs x :: Int)+(id _ :: Int,abs 0 :: Int)+(id _ :: Int,abs (id _) :: Int)+(id _ :: Int,_ + x :: Int)+(id _ :: Int,_ + 0 :: Int)+(id _ :: Int,_ + id _ :: Int)+(id _ :: Int,x + _ :: Int)+(id _ :: Int,0 + _ :: Int)+(id _ :: Int,id _ + _ :: Int)+(id _ :: Int,_ * _ :: Int)+(id _ :: Int,f _ :: Int)+(id _ :: Int,head xs :: Int)+(id _ :: Int,head [] :: Int)+(id _ :: Int,head (_:_) :: Int)+(id _ :: Int,ord c :: Int)+(id _ :: Int,ord 'a' :: Int)+(id _ :: Int,q :: Bool)+(id _ :: Int,not p :: Bool)+(id _ :: Int,not False :: Bool)+(id _ :: Int,not True :: Bool)+(id _ :: Int,not (not _) :: Bool)+(id _ :: Int,_ || _ :: Bool)+(id _ :: Int,d :: Char)+(id _ :: Int,' ' :: Char)+(id _ :: Int,ys :: [Int])+(id _ :: Int,[0] :: [Int])+(id _ :: Int,_:xs :: [Int])+(id _ :: Int,[_] :: [Int])+(id _ :: Int,_:_:_ :: [Int])+(id _ :: Int,x:_ :: [Int])+(id _ :: Int,0:_ :: [Int])+(id _ :: Int,id _:_ :: [Int])+(id _ :: Int,tail _ :: [Int])+(id _ :: Int,_ ++ _ :: [Int])+(id _ :: Int,negate :: Int -> Int)+(id _ :: Int,abs :: Int -> Int)+(id _ :: Int,(_ +) :: Int -> Int)+(id _ :: Int,(*) :: Int -> Int -> Int)+(id _ :: Int,not :: Bool -> Bool)+(id _ :: Int,(||) :: Bool -> Bool -> Bool)+(_ :: Bool,z :: Int)+(_ :: Bool,-1 :: Int)+(_ :: Bool,id y :: Int)+(_ :: Bool,id 1 :: Int)+(_ :: Bool,id (id x) :: Int)+(_ :: Bool,id (id 0) :: Int)+(_ :: Bool,id (id (id _)) :: Int)+(_ :: Bool,id (negate _) :: Int)+(_ :: Bool,id (abs _) :: Int)+(_ :: Bool,id (_ + _) :: Int)+(_ :: Bool,id (head _) :: Int)+(_ :: Bool,id (ord _) :: Int)+(_ :: Bool,negate x :: Int)+(_ :: Bool,negate 0 :: Int)+(_ :: Bool,negate (id _) :: Int)+(_ :: Bool,abs x :: Int)+(_ :: Bool,abs 0 :: Int)+(_ :: Bool,abs (id _) :: Int)+(_ :: Bool,_ + x :: Int)+(_ :: Bool,_ + 0 :: Int)+(_ :: Bool,_ + id _ :: Int)+(_ :: Bool,x + _ :: Int)+(_ :: Bool,0 + _ :: Int)+(_ :: Bool,id _ + _ :: Int)+(_ :: Bool,_ * _ :: Int)+(_ :: Bool,f _ :: Int)+(_ :: Bool,head xs :: Int)+(_ :: Bool,head [] :: Int)+(_ :: Bool,head (_:_) :: Int)+(_ :: Bool,ord c :: Int)+(_ :: Bool,ord 'a' :: Int)+(_ :: Bool,q :: Bool)+(_ :: Bool,not p :: Bool)+(_ :: Bool,not False :: Bool)+(_ :: Bool,not True :: Bool)+(_ :: Bool,not (not _) :: Bool)+(_ :: Bool,_ || _ :: Bool)+(_ :: Bool,d :: Char)+(_ :: Bool,' ' :: Char)+(_ :: Bool,ys :: [Int])+(_ :: Bool,[0] :: [Int])+(_ :: Bool,_:xs :: [Int])+(_ :: Bool,[_] :: [Int])+(_ :: Bool,_:_:_ :: [Int])+(_ :: Bool,x:_ :: [Int])+(_ :: Bool,0:_ :: [Int])+(_ :: Bool,id _:_ :: [Int])+(_ :: Bool,tail _ :: [Int])+(_ :: Bool,_ ++ _ :: [Int])+(_ :: Bool,negate :: Int -> Int)+(_ :: Bool,abs :: Int -> Int)+(_ :: Bool,(_ +) :: Int -> Int)+(_ :: Bool,(*) :: Int -> Int -> Int)+(_ :: Bool,not :: Bool -> Bool)+(_ :: Bool,(||) :: Bool -> Bool -> Bool)+(_ :: Char,z :: Int)+(_ :: Char,-1 :: Int)+(_ :: Char,id y :: Int)+(_ :: Char,id 1 :: Int)+(_ :: Char,id (id x) :: Int)+(_ :: Char,id (id 0) :: Int)+(_ :: Char,id (id (id _)) :: Int)+(_ :: Char,id (negate _) :: Int)+(_ :: Char,id (abs _) :: Int)+(_ :: Char,id (_ + _) :: Int)+(_ :: Char,id (head _) :: Int)+(_ :: Char,id (ord _) :: Int)+(_ :: Char,negate x :: Int)+(_ :: Char,negate 0 :: Int)+(_ :: Char,negate (id _) :: Int)+(_ :: Char,abs x :: Int)+(_ :: Char,abs 0 :: Int)+(_ :: Char,abs (id _) :: Int)+(_ :: Char,_ + x :: Int)+(_ :: Char,_ + 0 :: Int)+(_ :: Char,_ + id _ :: Int)+(_ :: Char,x + _ :: Int)+(_ :: Char,0 + _ :: Int)+(_ :: Char,id _ + _ :: Int)+(_ :: Char,_ * _ :: Int)+(_ :: Char,f _ :: Int)+(_ :: Char,head xs :: Int)+(_ :: Char,head [] :: Int)+(_ :: Char,head (_:_) :: Int)+(_ :: Char,ord c :: Int)+(_ :: Char,ord 'a' :: Int)+(_ :: Char,q :: Bool)+(_ :: Char,not p :: Bool)+(_ :: Char,not False :: Bool)+(_ :: Char,not True :: Bool)+(_ :: Char,not (not _) :: Bool)+(_ :: Char,_ || _ :: Bool)+(_ :: Char,d :: Char)+(_ :: Char,' ' :: Char)+(_ :: Char,ys :: [Int])+(_ :: Char,[0] :: [Int])+(_ :: Char,_:xs :: [Int])+(_ :: Char,[_] :: [Int])+(_ :: Char,_:_:_ :: [Int])+(_ :: Char,x:_ :: [Int])+(_ :: Char,0:_ :: [Int])+(_ :: Char,id _:_ :: [Int])+(_ :: Char,tail _ :: [Int])+(_ :: Char,_ ++ _ :: [Int])+(_ :: Char,negate :: Int -> Int)+(_ :: Char,abs :: Int -> Int)+(_ :: Char,(_ +) :: Int -> Int)+(_ :: Char,(*) :: Int -> Int -> Int)+(_ :: Char,not :: Bool -> Bool)+(_ :: Char,(||) :: Bool -> Bool -> Bool)+(_ :: [Int],z :: Int)+(_ :: [Int],-1 :: Int)+(_ :: [Int],id y :: Int)+(_ :: [Int],id 1 :: Int)+(_ :: [Int],id (id x) :: Int)+(_ :: [Int],id (id 0) :: Int)+(_ :: [Int],id (id (id _)) :: Int)+(_ :: [Int],id (negate _) :: Int)+(_ :: [Int],id (abs _) :: Int)+(_ :: [Int],id (_ + _) :: Int)+(_ :: [Int],id (head _) :: Int)+(_ :: [Int],id (ord _) :: Int)+(_ :: [Int],negate x :: Int)+(_ :: [Int],negate 0 :: Int)+(_ :: [Int],negate (id _) :: Int)+(_ :: [Int],abs x :: Int)+(_ :: [Int],abs 0 :: Int)+(_ :: [Int],abs (id _) :: Int)+(_ :: [Int],_ + x :: Int)+(_ :: [Int],_ + 0 :: Int)+(_ :: [Int],_ + id _ :: Int)+(_ :: [Int],x + _ :: Int)+(_ :: [Int],0 + _ :: Int)+(_ :: [Int],id _ + _ :: Int)+(_ :: [Int],_ * _ :: Int)+(_ :: [Int],f _ :: Int)+(_ :: [Int],head xs :: Int)+(_ :: [Int],head [] :: Int)+(_ :: [Int],head (_:_) :: Int)+(_ :: [Int],ord c :: Int)+(_ :: [Int],ord 'a' :: Int)+(_ :: [Int],q :: Bool)+(_ :: [Int],not p :: Bool)+(_ :: [Int],not False :: Bool)+(_ :: [Int],not True :: Bool)+(_ :: [Int],not (not _) :: Bool)+(_ :: [Int],_ || _ :: Bool)+(_ :: [Int],d :: Char)+(_ :: [Int],' ' :: Char)+(_ :: [Int],ys :: [Int])+(_ :: [Int],[0] :: [Int])+(_ :: [Int],_:xs :: [Int])+(_ :: [Int],[_] :: [Int])+(_ :: [Int],_:_:_ :: [Int])+(_ :: [Int],x:_ :: [Int])+(_ :: [Int],0:_ :: [Int])+(_ :: [Int],id _:_ :: [Int])+(_ :: [Int],tail _ :: [Int])+(_ :: [Int],_ ++ _ :: [Int])+(_ :: [Int],negate :: Int -> Int)+(_ :: [Int],abs :: Int -> Int)+(_ :: [Int],(_ +) :: Int -> Int)+(_ :: [Int],(*) :: Int -> Int -> Int)+(_ :: [Int],not :: Bool -> Bool)+(_ :: [Int],(||) :: Bool -> Bool -> Bool)+(y :: Int,y :: Int)+(y :: Int,1 :: Int)+(y :: Int,id x :: Int)+(y :: Int,id 0 :: Int)+(y :: Int,id (id _) :: Int)+(y :: Int,negate _ :: Int)+(y :: Int,abs _ :: Int)+(y :: Int,_ + _ :: Int)+(y :: Int,head _ :: Int)+(y :: Int,ord _ :: Int)+(y :: Int,p :: Bool)+(y :: Int,False :: Bool)+(y :: Int,True :: Bool)+(y :: Int,not _ :: Bool)+(y :: Int,c :: Char)+(y :: Int,'a' :: Char)+(y :: Int,xs :: [Int])+(y :: Int,[] :: [Int])+(y :: Int,_:_ :: [Int])+(y :: Int,id :: Int -> Int)+(y :: Int,(+) :: Int -> Int -> Int)+(1 :: Int,y :: Int)+(1 :: Int,1 :: Int)+(1 :: Int,id x :: Int)+(1 :: Int,id 0 :: Int)+(1 :: Int,id (id _) :: Int)+(1 :: Int,negate _ :: Int)+(1 :: Int,abs _ :: Int)+(1 :: Int,_ + _ :: Int)+(1 :: Int,head _ :: Int)+(1 :: Int,ord _ :: Int)+(1 :: Int,p :: Bool)+(1 :: Int,False :: Bool)+(1 :: Int,True :: Bool)+(1 :: Int,not _ :: Bool)+(1 :: Int,c :: Char)+(1 :: Int,'a' :: Char)+(1 :: Int,xs :: [Int])+(1 :: Int,[] :: [Int])+(1 :: Int,_:_ :: [Int])+
+ test/model/bench/tiers.out view
@@ -0,0 +1,3624 @@+isNub (list :: [Expr]) = True+map length (tiers :: [[ Expr ]]) = [1,6,21,55,177,674,2679,11128,47899,...]+tiers :: [[ Expr ]] =+ [ [_ :: Int]+ , [ x :: Int+ , 0 :: Int+ , id _ :: Int+ , _ :: Bool+ , _ :: Char+ , _ :: [Int]+ ]+ , [ y :: Int+ , 1 :: Int+ , id x :: Int+ , id 0 :: Int+ , id (id _) :: Int+ , negate _ :: Int+ , abs _ :: Int+ , _ + _ :: Int+ , head _ :: Int+ , ord _ :: Int+ , p :: Bool+ , False :: Bool+ , True :: Bool+ , not _ :: Bool+ , c :: Char+ , 'a' :: Char+ , xs :: [Int]+ , [] :: [Int]+ , _:_ :: [Int]+ , id :: Int -> Int+ , (+) :: Int -> Int -> Int+ ]+ , [ z :: Int+ , -1 :: Int+ , id y :: Int+ , id 1 :: Int+ , id (id x) :: Int+ , id (id 0) :: Int+ , id (id (id _)) :: Int+ , id (negate _) :: Int+ , id (abs _) :: Int+ , id (_ + _) :: Int+ , id (head _) :: Int+ , id (ord _) :: Int+ , negate x :: Int+ , negate 0 :: Int+ , negate (id _) :: Int+ , abs x :: Int+ , abs 0 :: Int+ , abs (id _) :: Int+ , _ + x :: Int+ , _ + 0 :: Int+ , _ + id _ :: Int+ , x + _ :: Int+ , 0 + _ :: Int+ , id _ + _ :: Int+ , _ * _ :: Int+ , f _ :: Int+ , head xs :: Int+ , head [] :: Int+ , head (_:_) :: Int+ , ord c :: Int+ , ord 'a' :: Int+ , q :: Bool+ , not p :: Bool+ , not False :: Bool+ , not True :: Bool+ , not (not _) :: Bool+ , _ || _ :: Bool+ , d :: Char+ , ' ' :: Char+ , ys :: [Int]+ , [0] :: [Int]+ , _:xs :: [Int]+ , [_] :: [Int]+ , _:_:_ :: [Int]+ , x:_ :: [Int]+ , 0:_ :: [Int]+ , id _:_ :: [Int]+ , tail _ :: [Int]+ , _ ++ _ :: [Int]+ , negate :: Int -> Int+ , abs :: Int -> Int+ , (_ +) :: Int -> Int+ , (*) :: Int -> Int -> Int+ , not :: Bool -> Bool+ , (||) :: Bool -> Bool -> Bool+ ]+ , [ x' :: Int+ , 2 :: Int+ , id z :: Int+ , id (-1) :: Int+ , id (id y) :: Int+ , id (id 1) :: Int+ , id (id (id x)) :: Int+ , id (id (id 0)) :: Int+ , id (id (id (id _))) :: Int+ , id (id (negate _)) :: Int+ , id (id (abs _)) :: Int+ , id (id (_ + _)) :: Int+ , id (id (head _)) :: Int+ , id (id (ord _)) :: Int+ , id (negate x) :: Int+ , id (negate 0) :: Int+ , id (negate (id _)) :: Int+ , id (abs x) :: Int+ , id (abs 0) :: Int+ , id (abs (id _)) :: Int+ , id (_ + x) :: Int+ , id (_ + 0) :: Int+ , id (_ + id _) :: Int+ , id (x + _) :: Int+ , id (0 + _) :: Int+ , id (id _ + _) :: Int+ , id (_ * _) :: Int+ , id (f _) :: Int+ , id (head xs) :: Int+ , id (head []) :: Int+ , id (head (_:_)) :: Int+ , id (ord c) :: Int+ , id (ord 'a') :: Int+ , negate y :: Int+ , negate 1 :: Int+ , negate (id x) :: Int+ , negate (id 0) :: Int+ , negate (id (id _)) :: Int+ , negate (negate _) :: Int+ , negate (abs _) :: Int+ , negate (_ + _) :: Int+ , negate (head _) :: Int+ , negate (ord _) :: Int+ , abs y :: Int+ , abs 1 :: Int+ , abs (id x) :: Int+ , abs (id 0) :: Int+ , abs (id (id _)) :: Int+ , abs (negate _) :: Int+ , abs (abs _) :: Int+ , abs (_ + _) :: Int+ , abs (head _) :: Int+ , abs (ord _) :: Int+ , _ + y :: Int+ , _ + 1 :: Int+ , _ + id x :: Int+ , _ + id 0 :: Int+ , _ + id (id _) :: Int+ , _ + negate _ :: Int+ , _ + abs _ :: Int+ , _ + (_ + _) :: Int+ , _ + head _ :: Int+ , _ + ord _ :: Int+ , x + x :: Int+ , x + 0 :: Int+ , x + id _ :: Int+ , 0 + x :: Int+ , 0 + 0 :: Int+ , 0 + id _ :: Int+ , id _ + x :: Int+ , id _ + 0 :: Int+ , id _ + id _ :: Int+ , _ * x :: Int+ , _ * 0 :: Int+ , _ * id _ :: Int+ , f x :: Int+ , f 0 :: Int+ , f (id _) :: Int+ , y + _ :: Int+ , 1 + _ :: Int+ , id x + _ :: Int+ , id 0 + _ :: Int+ , id (id _) + _ :: Int+ , negate _ + _ :: Int+ , abs _ + _ :: Int+ , (_ + _) + _ :: Int+ , head _ + _ :: Int+ , ord _ + _ :: Int+ , x * _ :: Int+ , 0 * _ :: Int+ , id _ * _ :: Int+ , g _ :: Int+ , head ys :: Int+ , head [0] :: Int+ , head (_:xs) :: Int+ , head [_] :: Int+ , head (_:_:_) :: Int+ , head (x:_) :: Int+ , head (0:_) :: Int+ , head (id _:_) :: Int+ , head (tail _) :: Int+ , head (_ ++ _) :: Int+ , ord d :: Int+ , ord ' ' :: Int+ , r :: Bool+ , not q :: Bool+ , not (not p) :: Bool+ , not (not False) :: Bool+ , not (not True) :: Bool+ , not (not (not _)) :: Bool+ , not (_ || _) :: Bool+ , _ || p :: Bool+ , _ || False :: Bool+ , _ || True :: Bool+ , _ || not _ :: Bool+ , p || _ :: Bool+ , False || _ :: Bool+ , True || _ :: Bool+ , not _ || _ :: Bool+ , _ && _ :: Bool+ , _ == _ :: Bool+ , _ == _ :: Bool+ , odd _ :: Bool+ , even _ :: Bool+ , elem _ _ :: Bool+ , e :: Char+ , 'b' :: Char+ , zs :: [Int]+ , [0,0] :: [Int]+ , [1] :: [Int]+ , _:ys :: [Int]+ , [_,0] :: [Int]+ , _:_:xs :: [Int]+ , [_,_] :: [Int]+ , _:_:_:_ :: [Int]+ , _:x:_ :: [Int]+ , _:0:_ :: [Int]+ , _:id _:_ :: [Int]+ , _:tail _ :: [Int]+ , _:(_ ++ _) :: [Int]+ , x:xs :: [Int]+ , [x] :: [Int]+ , x:_:_ :: [Int]+ , 0:xs :: [Int]+ , [0] :: [Int]+ , 0:_:_ :: [Int]+ , id _:xs :: [Int]+ , [id _] :: [Int]+ , id _:_:_ :: [Int]+ , y:_ :: [Int]+ , 1:_ :: [Int]+ , id x:_ :: [Int]+ , id 0:_ :: [Int]+ , id (id _):_ :: [Int]+ , negate _:_ :: [Int]+ , abs _:_ :: [Int]+ , _ + _:_ :: [Int]+ , head _:_ :: [Int]+ , ord _:_ :: [Int]+ , tail xs :: [Int]+ , tail [] :: [Int]+ , tail (_:_) :: [Int]+ , _ ++ xs :: [Int]+ , _ ++ [] :: [Int]+ , _ ++ (_:_) :: [Int]+ , xs ++ _ :: [Int]+ , [] ++ _ :: [Int]+ , (_:_) ++ _ :: [Int]+ , sort _ :: [Int]+ , insert _ _ :: [Int]+ , (x +) :: Int -> Int+ , (0 +) :: Int -> Int+ , (id _ +) :: Int -> Int+ , (_ *) :: Int -> Int+ , f :: Int -> Int+ , (_ ||) :: Bool -> Bool+ , (&&) :: Bool -> Bool -> Bool+ ]+ , [ y' :: Int+ , -2 :: Int+ , id x' :: Int+ , id 2 :: Int+ , id (id z) :: Int+ , id (id (-1)) :: Int+ , id (id (id y)) :: Int+ , id (id (id 1)) :: Int+ , id (id (id (id x))) :: Int+ , id (id (id (id 0))) :: Int+ , id (id (id (id (id _)))) :: Int+ , id (id (id (negate _))) :: Int+ , id (id (id (abs _))) :: Int+ , id (id (id (_ + _))) :: Int+ , id (id (id (head _))) :: Int+ , id (id (id (ord _))) :: Int+ , id (id (negate x)) :: Int+ , id (id (negate 0)) :: Int+ , id (id (negate (id _))) :: Int+ , id (id (abs x)) :: Int+ , id (id (abs 0)) :: Int+ , id (id (abs (id _))) :: Int+ , id (id (_ + x)) :: Int+ , id (id (_ + 0)) :: Int+ , id (id (_ + id _)) :: Int+ , id (id (x + _)) :: Int+ , id (id (0 + _)) :: Int+ , id (id (id _ + _)) :: Int+ , id (id (_ * _)) :: Int+ , id (id (f _)) :: Int+ , id (id (head xs)) :: Int+ , id (id (head [])) :: Int+ , id (id (head (_:_))) :: Int+ , id (id (ord c)) :: Int+ , id (id (ord 'a')) :: Int+ , id (negate y) :: Int+ , id (negate 1) :: Int+ , id (negate (id x)) :: Int+ , id (negate (id 0)) :: Int+ , id (negate (id (id _))) :: Int+ , id (negate (negate _)) :: Int+ , id (negate (abs _)) :: Int+ , id (negate (_ + _)) :: Int+ , id (negate (head _)) :: Int+ , id (negate (ord _)) :: Int+ , id (abs y) :: Int+ , id (abs 1) :: Int+ , id (abs (id x)) :: Int+ , id (abs (id 0)) :: Int+ , id (abs (id (id _))) :: Int+ , id (abs (negate _)) :: Int+ , id (abs (abs _)) :: Int+ , id (abs (_ + _)) :: Int+ , id (abs (head _)) :: Int+ , id (abs (ord _)) :: Int+ , id (_ + y) :: Int+ , id (_ + 1) :: Int+ , id (_ + id x) :: Int+ , id (_ + id 0) :: Int+ , id (_ + id (id _)) :: Int+ , id (_ + negate _) :: Int+ , id (_ + abs _) :: Int+ , id (_ + (_ + _)) :: Int+ , id (_ + head _) :: Int+ , id (_ + ord _) :: Int+ , id (x + x) :: Int+ , id (x + 0) :: Int+ , id (x + id _) :: Int+ , id (0 + x) :: Int+ , id (0 + 0) :: Int+ , id (0 + id _) :: Int+ , id (id _ + x) :: Int+ , id (id _ + 0) :: Int+ , id (id _ + id _) :: Int+ , id (_ * x) :: Int+ , id (_ * 0) :: Int+ , id (_ * id _) :: Int+ , id (f x) :: Int+ , id (f 0) :: Int+ , id (f (id _)) :: Int+ , id (y + _) :: Int+ , id (1 + _) :: Int+ , id (id x + _) :: Int+ , id (id 0 + _) :: Int+ , id (id (id _) + _) :: Int+ , id (negate _ + _) :: Int+ , id (abs _ + _) :: Int+ , id ((_ + _) + _) :: Int+ , id (head _ + _) :: Int+ , id (ord _ + _) :: Int+ , id (x * _) :: Int+ , id (0 * _) :: Int+ , id (id _ * _) :: Int+ , id (g _) :: Int+ , id (head ys) :: Int+ , id (head [0]) :: Int+ , id (head (_:xs)) :: Int+ , id (head [_]) :: Int+ , id (head (_:_:_)) :: Int+ , id (head (x:_)) :: Int+ , id (head (0:_)) :: Int+ , id (head (id _:_)) :: Int+ , id (head (tail _)) :: Int+ , id (head (_ ++ _)) :: Int+ , id (ord d) :: Int+ , id (ord ' ') :: Int+ , negate z :: Int+ , negate (-1) :: Int+ , negate (id y) :: Int+ , negate (id 1) :: Int+ , negate (id (id x)) :: Int+ , negate (id (id 0)) :: Int+ , negate (id (id (id _))) :: Int+ , negate (id (negate _)) :: Int+ , negate (id (abs _)) :: Int+ , negate (id (_ + _)) :: Int+ , negate (id (head _)) :: Int+ , negate (id (ord _)) :: Int+ , negate (negate x) :: Int+ , negate (negate 0) :: Int+ , negate (negate (id _)) :: Int+ , negate (abs x) :: Int+ , negate (abs 0) :: Int+ , negate (abs (id _)) :: Int+ , negate (_ + x) :: Int+ , negate (_ + 0) :: Int+ , negate (_ + id _) :: Int+ , negate (x + _) :: Int+ , negate (0 + _) :: Int+ , negate (id _ + _) :: Int+ , negate (_ * _) :: Int+ , negate (f _) :: Int+ , negate (head xs) :: Int+ , negate (head []) :: Int+ , negate (head (_:_)) :: Int+ , negate (ord c) :: Int+ , negate (ord 'a') :: Int+ , abs z :: Int+ , abs (-1) :: Int+ , abs (id y) :: Int+ , abs (id 1) :: Int+ , abs (id (id x)) :: Int+ , abs (id (id 0)) :: Int+ , abs (id (id (id _))) :: Int+ , abs (id (negate _)) :: Int+ , abs (id (abs _)) :: Int+ , abs (id (_ + _)) :: Int+ , abs (id (head _)) :: Int+ , abs (id (ord _)) :: Int+ , abs (negate x) :: Int+ , abs (negate 0) :: Int+ , abs (negate (id _)) :: Int+ , abs (abs x) :: Int+ , abs (abs 0) :: Int+ , abs (abs (id _)) :: Int+ , abs (_ + x) :: Int+ , abs (_ + 0) :: Int+ , abs (_ + id _) :: Int+ , abs (x + _) :: Int+ , abs (0 + _) :: Int+ , abs (id _ + _) :: Int+ , abs (_ * _) :: Int+ , abs (f _) :: Int+ , abs (head xs) :: Int+ , abs (head []) :: Int+ , abs (head (_:_)) :: Int+ , abs (ord c) :: Int+ , abs (ord 'a') :: Int+ , _ + z :: Int+ , _ + (-1) :: Int+ , _ + id y :: Int+ , _ + id 1 :: Int+ , _ + id (id x) :: Int+ , _ + id (id 0) :: Int+ , _ + id (id (id _)) :: Int+ , _ + id (negate _) :: Int+ , _ + id (abs _) :: Int+ , _ + id (_ + _) :: Int+ , _ + id (head _) :: Int+ , _ + id (ord _) :: Int+ , _ + negate x :: Int+ , _ + negate 0 :: Int+ , _ + negate (id _) :: Int+ , _ + abs x :: Int+ , _ + abs 0 :: Int+ , _ + abs (id _) :: Int+ , _ + (_ + x) :: Int+ , _ + (_ + 0) :: Int+ , _ + (_ + id _) :: Int+ , _ + (x + _) :: Int+ , _ + (0 + _) :: Int+ , _ + (id _ + _) :: Int+ , _ + _ * _ :: Int+ , _ + f _ :: Int+ , _ + head xs :: Int+ , _ + head [] :: Int+ , _ + head (_:_) :: Int+ , _ + ord c :: Int+ , _ + ord 'a' :: Int+ , x + y :: Int+ , x + 1 :: Int+ , x + id x :: Int+ , x + id 0 :: Int+ , x + id (id _) :: Int+ , x + negate _ :: Int+ , x + abs _ :: Int+ , x + (_ + _) :: Int+ , x + head _ :: Int+ , x + ord _ :: Int+ , 0 + y :: Int+ , 0 + 1 :: Int+ , 0 + id x :: Int+ , 0 + id 0 :: Int+ , 0 + id (id _) :: Int+ , 0 + negate _ :: Int+ , 0 + abs _ :: Int+ , 0 + (_ + _) :: Int+ , 0 + head _ :: Int+ , 0 + ord _ :: Int+ , id _ + y :: Int+ , id _ + 1 :: Int+ , id _ + id x :: Int+ , id _ + id 0 :: Int+ , id _ + id (id _) :: Int+ , id _ + negate _ :: Int+ , id _ + abs _ :: Int+ , id _ + (_ + _) :: Int+ , id _ + head _ :: Int+ , id _ + ord _ :: Int+ , _ * y :: Int+ , _ * 1 :: Int+ , _ * id x :: Int+ , _ * id 0 :: Int+ , _ * id (id _) :: Int+ , _ * negate _ :: Int+ , _ * abs _ :: Int+ , _ * (_ + _) :: Int+ , _ * head _ :: Int+ , _ * ord _ :: Int+ , f y :: Int+ , f 1 :: Int+ , f (id x) :: Int+ , f (id 0) :: Int+ , f (id (id _)) :: Int+ , f (negate _) :: Int+ , f (abs _) :: Int+ , f (_ + _) :: Int+ , f (head _) :: Int+ , f (ord _) :: Int+ , y + x :: Int+ , y + 0 :: Int+ , y + id _ :: Int+ , 1 + x :: Int+ , 1 + 0 :: Int+ , 1 + id _ :: Int+ , id x + x :: Int+ , id x + 0 :: Int+ , id x + id _ :: Int+ , id 0 + x :: Int+ , id 0 + 0 :: Int+ , id 0 + id _ :: Int+ , id (id _) + x :: Int+ , id (id _) + 0 :: Int+ , id (id _) + id _ :: Int+ , negate _ + x :: Int+ , negate _ + 0 :: Int+ , negate _ + id _ :: Int+ , abs _ + x :: Int+ , abs _ + 0 :: Int+ , abs _ + id _ :: Int+ , (_ + _) + x :: Int+ , (_ + _) + 0 :: Int+ , (_ + _) + id _ :: Int+ , head _ + x :: Int+ , head _ + 0 :: Int+ , head _ + id _ :: Int+ , ord _ + x :: Int+ , ord _ + 0 :: Int+ , ord _ + id _ :: Int+ , x * x :: Int+ , x * 0 :: Int+ , x * id _ :: Int+ , 0 * x :: Int+ , 0 * 0 :: Int+ , 0 * id _ :: Int+ , id _ * x :: Int+ , id _ * 0 :: Int+ , id _ * id _ :: Int+ , g x :: Int+ , g 0 :: Int+ , g (id _) :: Int+ , z + _ :: Int+ , (-1) + _ :: Int+ , id y + _ :: Int+ , id 1 + _ :: Int+ , id (id x) + _ :: Int+ , id (id 0) + _ :: Int+ , id (id (id _)) + _ :: Int+ , id (negate _) + _ :: Int+ , id (abs _) + _ :: Int+ , id (_ + _) + _ :: Int+ , id (head _) + _ :: Int+ , id (ord _) + _ :: Int+ , negate x + _ :: Int+ , negate 0 + _ :: Int+ , negate (id _) + _ :: Int+ , abs x + _ :: Int+ , abs 0 + _ :: Int+ , abs (id _) + _ :: Int+ , (_ + x) + _ :: Int+ , (_ + 0) + _ :: Int+ , (_ + id _) + _ :: Int+ , (x + _) + _ :: Int+ , (0 + _) + _ :: Int+ , (id _ + _) + _ :: Int+ , _ * _ + _ :: Int+ , f _ + _ :: Int+ , head xs + _ :: Int+ , head [] + _ :: Int+ , head (_:_) + _ :: Int+ , ord c + _ :: Int+ , ord 'a' + _ :: Int+ , y * _ :: Int+ , 1 * _ :: Int+ , id x * _ :: Int+ , id 0 * _ :: Int+ , id (id _) * _ :: Int+ , negate _ * _ :: Int+ , abs _ * _ :: Int+ , (_ + _) * _ :: Int+ , head _ * _ :: Int+ , ord _ * _ :: Int+ , h _ :: Int+ , head zs :: Int+ , head [0,0] :: Int+ , head [1] :: Int+ , head (_:ys) :: Int+ , head [_,0] :: Int+ , head (_:_:xs) :: Int+ , head [_,_] :: Int+ , head (_:_:_:_) :: Int+ , head (_:x:_) :: Int+ , head (_:0:_) :: Int+ , head (_:id _:_) :: Int+ , head (_:tail _) :: Int+ , head (_:(_ ++ _)) :: Int+ , head (x:xs) :: Int+ , head [x] :: Int+ , head (x:_:_) :: Int+ , head (0:xs) :: Int+ , head [0] :: Int+ , head (0:_:_) :: Int+ , head (id _:xs) :: Int+ , head [id _] :: Int+ , head (id _:_:_) :: Int+ , head (y:_) :: Int+ , head (1:_) :: Int+ , head (id x:_) :: Int+ , head (id 0:_) :: Int+ , head (id (id _):_) :: Int+ , head (negate _:_) :: Int+ , head (abs _:_) :: Int+ , head (_ + _:_) :: Int+ , head (head _:_) :: Int+ , head (ord _:_) :: Int+ , head (tail xs) :: Int+ , head (tail []) :: Int+ , head (tail (_:_)) :: Int+ , head (_ ++ xs) :: Int+ , head (_ ++ []) :: Int+ , head (_ ++ (_:_)) :: Int+ , head (xs ++ _) :: Int+ , head ([] ++ _) :: Int+ , head ((_:_) ++ _) :: Int+ , head (sort _) :: Int+ , head (insert _ _) :: Int+ , ord e :: Int+ , ord 'b' :: Int+ , p' :: Bool+ , not r :: Bool+ , not (not q) :: Bool+ , not (not (not p)) :: Bool+ , not (not (not False)) :: Bool+ , not (not (not True)) :: Bool+ , not (not (not (not _))) :: Bool+ , not (not (_ || _)) :: Bool+ , not (_ || p) :: Bool+ , not (_ || False) :: Bool+ , not (_ || True) :: Bool+ , not (_ || not _) :: Bool+ , not (p || _) :: Bool+ , not (False || _) :: Bool+ , not (True || _) :: Bool+ , not (not _ || _) :: Bool+ , not (_ && _) :: Bool+ , not (_ == _) :: Bool+ , not (_ == _) :: Bool+ , not (odd _) :: Bool+ , not (even _) :: Bool+ , not (elem _ _) :: Bool+ , _ || q :: Bool+ , _ || not p :: Bool+ , _ || not False :: Bool+ , _ || not True :: Bool+ , _ || not (not _) :: Bool+ , _ || (_ || _) :: Bool+ , p || p :: Bool+ , p || False :: Bool+ , p || True :: Bool+ , p || not _ :: Bool+ , False || p :: Bool+ , False || False :: Bool+ , False || True :: Bool+ , False || not _ :: Bool+ , True || p :: Bool+ , True || False :: Bool+ , True || True :: Bool+ , True || not _ :: Bool+ , not _ || p :: Bool+ , not _ || False :: Bool+ , not _ || True :: Bool+ , not _ || not _ :: Bool+ , _ && p :: Bool+ , _ && False :: Bool+ , _ && True :: Bool+ , _ && not _ :: Bool+ , q || _ :: Bool+ , not p || _ :: Bool+ , not False || _ :: Bool+ , not True || _ :: Bool+ , not (not _) || _ :: Bool+ , (_ || _) || _ :: Bool+ , p && _ :: Bool+ , False && _ :: Bool+ , True && _ :: Bool+ , not _ && _ :: Bool+ , _ ==> _ :: Bool+ , _ == x :: Bool+ , _ == 0 :: Bool+ , _ == id _ :: Bool+ , x == _ :: Bool+ , 0 == _ :: Bool+ , id _ == _ :: Bool+ , _ == p :: Bool+ , _ == False :: Bool+ , _ == True :: Bool+ , _ == not _ :: Bool+ , p == _ :: Bool+ , False == _ :: Bool+ , True == _ :: Bool+ , not _ == _ :: Bool+ , _ <= _ :: Bool+ , _ <= _ :: Bool+ , odd x :: Bool+ , odd 0 :: Bool+ , odd (id _) :: Bool+ , even x :: Bool+ , even 0 :: Bool+ , even (id _) :: Bool+ , elem _ xs :: Bool+ , elem _ [] :: Bool+ , elem _ (_:_) :: Bool+ , elem x _ :: Bool+ , elem 0 _ :: Bool+ , elem (id _) _ :: Bool+ , c' :: Char+ , 'A' :: Char+ , xs' :: [Int]+ , [0,0,0] :: [Int]+ , [0,1] :: [Int]+ , [1,0] :: [Int]+ , [-1] :: [Int]+ , _:zs :: [Int]+ , [_,0,0] :: [Int]+ , [_,1] :: [Int]+ , _:_:ys :: [Int]+ , [_,_,0] :: [Int]+ , _:_:_:xs :: [Int]+ , [_,_,_] :: [Int]+ , _:_:_:_:_ :: [Int]+ , _:_:x:_ :: [Int]+ , _:_:0:_ :: [Int]+ , _:_:id _:_ :: [Int]+ , _:_:tail _ :: [Int]+ , _:_:(_ ++ _) :: [Int]+ , _:x:xs :: [Int]+ , [_,x] :: [Int]+ , _:x:_:_ :: [Int]+ , _:0:xs :: [Int]+ , [_,0] :: [Int]+ , _:0:_:_ :: [Int]+ , _:id _:xs :: [Int]+ , [_,id _] :: [Int]+ , _:id _:_:_ :: [Int]+ , _:y:_ :: [Int]+ , _:1:_ :: [Int]+ , _:id x:_ :: [Int]+ , _:id 0:_ :: [Int]+ , _:id (id _):_ :: [Int]+ , _:negate _:_ :: [Int]+ , _:abs _:_ :: [Int]+ , _:_ + _:_ :: [Int]+ , _:head _:_ :: [Int]+ , _:ord _:_ :: [Int]+ , _:tail xs :: [Int]+ , _:tail [] :: [Int]+ , _:tail (_:_) :: [Int]+ , _:(_ ++ xs) :: [Int]+ , _:(_ ++ []) :: [Int]+ , _:(_ ++ (_:_)) :: [Int]+ , _:(xs ++ _) :: [Int]+ , _:([] ++ _) :: [Int]+ , _:((_:_) ++ _) :: [Int]+ , _:sort _ :: [Int]+ , _:insert _ _ :: [Int]+ , x:ys :: [Int]+ , [x,0] :: [Int]+ , x:_:xs :: [Int]+ , [x,_] :: [Int]+ , x:_:_:_ :: [Int]+ , x:x:_ :: [Int]+ , x:0:_ :: [Int]+ , x:id _:_ :: [Int]+ , x:tail _ :: [Int]+ , x:(_ ++ _) :: [Int]+ , 0:ys :: [Int]+ , [0,0] :: [Int]+ , 0:_:xs :: [Int]+ , [0,_] :: [Int]+ , 0:_:_:_ :: [Int]+ , 0:x:_ :: [Int]+ , 0:0:_ :: [Int]+ , 0:id _:_ :: [Int]+ , 0:tail _ :: [Int]+ , 0:(_ ++ _) :: [Int]+ , id _:ys :: [Int]+ , [id _,0] :: [Int]+ , id _:_:xs :: [Int]+ , [id _,_] :: [Int]+ , id _:_:_:_ :: [Int]+ , id _:x:_ :: [Int]+ , id _:0:_ :: [Int]+ , id _:id _:_ :: [Int]+ , id _:tail _ :: [Int]+ , id _:(_ ++ _) :: [Int]+ , y:xs :: [Int]+ , [y] :: [Int]+ , y:_:_ :: [Int]+ , 1:xs :: [Int]+ , [1] :: [Int]+ , 1:_:_ :: [Int]+ , id x:xs :: [Int]+ , [id x] :: [Int]+ , id x:_:_ :: [Int]+ , id 0:xs :: [Int]+ , [id 0] :: [Int]+ , id 0:_:_ :: [Int]+ , id (id _):xs :: [Int]+ , [id (id _)] :: [Int]+ , id (id _):_:_ :: [Int]+ , negate _:xs :: [Int]+ , [negate _] :: [Int]+ , negate _:_:_ :: [Int]+ , abs _:xs :: [Int]+ , [abs _] :: [Int]+ , abs _:_:_ :: [Int]+ , _ + _:xs :: [Int]+ , [_ + _] :: [Int]+ , _ + _:_:_ :: [Int]+ , head _:xs :: [Int]+ , [head _] :: [Int]+ , head _:_:_ :: [Int]+ , ord _:xs :: [Int]+ , [ord _] :: [Int]+ , ord _:_:_ :: [Int]+ , z:_ :: [Int]+ , (-1):_ :: [Int]+ , id y:_ :: [Int]+ , id 1:_ :: [Int]+ , id (id x):_ :: [Int]+ , id (id 0):_ :: [Int]+ , id (id (id _)):_ :: [Int]+ , id (negate _):_ :: [Int]+ , id (abs _):_ :: [Int]+ , id (_ + _):_ :: [Int]+ , id (head _):_ :: [Int]+ , id (ord _):_ :: [Int]+ , negate x:_ :: [Int]+ , negate 0:_ :: [Int]+ , negate (id _):_ :: [Int]+ , abs x:_ :: [Int]+ , abs 0:_ :: [Int]+ , abs (id _):_ :: [Int]+ , _ + x:_ :: [Int]+ , _ + 0:_ :: [Int]+ , _ + id _:_ :: [Int]+ , x + _:_ :: [Int]+ , 0 + _:_ :: [Int]+ , id _ + _:_ :: [Int]+ , _ * _:_ :: [Int]+ , f _:_ :: [Int]+ , head xs:_ :: [Int]+ , head []:_ :: [Int]+ , head (_:_):_ :: [Int]+ , ord c:_ :: [Int]+ , ord 'a':_ :: [Int]+ , tail ys :: [Int]+ , tail [0] :: [Int]+ , tail (_:xs) :: [Int]+ , tail [_] :: [Int]+ , tail (_:_:_) :: [Int]+ , tail (x:_) :: [Int]+ , tail (0:_) :: [Int]+ , tail (id _:_) :: [Int]+ , tail (tail _) :: [Int]+ , tail (_ ++ _) :: [Int]+ , _ ++ ys :: [Int]+ , _ ++ [0] :: [Int]+ , _ ++ (_:xs) :: [Int]+ , _ ++ [_] :: [Int]+ , _ ++ (_:_:_) :: [Int]+ , _ ++ (x:_) :: [Int]+ , _ ++ (0:_) :: [Int]+ , _ ++ (id _:_) :: [Int]+ , _ ++ tail _ :: [Int]+ , _ ++ (_ ++ _) :: [Int]+ , xs ++ xs :: [Int]+ , xs ++ [] :: [Int]+ , xs ++ (_:_) :: [Int]+ , [] ++ xs :: [Int]+ , [] ++ [] :: [Int]+ , [] ++ (_:_) :: [Int]+ , (_:_) ++ xs :: [Int]+ , (_:_) ++ [] :: [Int]+ , (_:_) ++ (_:_) :: [Int]+ , ys ++ _ :: [Int]+ , [0] ++ _ :: [Int]+ , (_:xs) ++ _ :: [Int]+ , [_] ++ _ :: [Int]+ , (_:_:_) ++ _ :: [Int]+ , (x:_) ++ _ :: [Int]+ , (0:_) ++ _ :: [Int]+ , (id _:_) ++ _ :: [Int]+ , tail _ ++ _ :: [Int]+ , (_ ++ _) ++ _ :: [Int]+ , sort xs :: [Int]+ , sort [] :: [Int]+ , sort (_:_) :: [Int]+ , insert _ xs :: [Int]+ , insert _ [] :: [Int]+ , insert _ (_:_) :: [Int]+ , insert x _ :: [Int]+ , insert 0 _ :: [Int]+ , insert (id _) _ :: [Int]+ , (y +) :: Int -> Int+ , (1 +) :: Int -> Int+ , (id x +) :: Int -> Int+ , (id 0 +) :: Int -> Int+ , (id (id _) +) :: Int -> Int+ , (negate _ +) :: Int -> Int+ , (abs _ +) :: Int -> Int+ , ((_ + _) +) :: Int -> Int+ , (head _ +) :: Int -> Int+ , (ord _ +) :: Int -> Int+ , (x *) :: Int -> Int+ , (0 *) :: Int -> Int+ , (id _ *) :: Int -> Int+ , g :: Int -> Int+ , (p ||) :: Bool -> Bool+ , (False ||) :: Bool -> Bool+ , (True ||) :: Bool -> Bool+ , (not _ ||) :: Bool -> Bool+ , (_ &&) :: Bool -> Bool+ , (==>) :: Bool -> Bool -> Bool+ ]+ , [ z' :: Int+ , 3 :: Int+ , id y' :: Int+ , id (-2) :: Int+ , id (id x') :: Int+ , id (id 2) :: Int+ , id (id (id z)) :: Int+ , id (id (id (-1))) :: Int+ , id (id (id (id y))) :: Int+ , id (id (id (id 1))) :: Int+ , id (id (id (id (id x)))) :: Int+ , id (id (id (id (id 0)))) :: Int+ , id (id (id (id (id (id _))))) :: Int+ , id (id (id (id (negate _)))) :: Int+ , id (id (id (id (abs _)))) :: Int+ , id (id (id (id (_ + _)))) :: Int+ , id (id (id (id (head _)))) :: Int+ , id (id (id (id (ord _)))) :: Int+ , id (id (id (negate x))) :: Int+ , id (id (id (negate 0))) :: Int+ , id (id (id (negate (id _)))) :: Int+ , id (id (id (abs x))) :: Int+ , id (id (id (abs 0))) :: Int+ , id (id (id (abs (id _)))) :: Int+ , id (id (id (_ + x))) :: Int+ , id (id (id (_ + 0))) :: Int+ , id (id (id (_ + id _))) :: Int+ , id (id (id (x + _))) :: Int+ , id (id (id (0 + _))) :: Int+ , id (id (id (id _ + _))) :: Int+ , id (id (id (_ * _))) :: Int+ , id (id (id (f _))) :: Int+ , id (id (id (head xs))) :: Int+ , id (id (id (head []))) :: Int+ , id (id (id (head (_:_)))) :: Int+ , id (id (id (ord c))) :: Int+ , id (id (id (ord 'a'))) :: Int+ , id (id (negate y)) :: Int+ , id (id (negate 1)) :: Int+ , id (id (negate (id x))) :: Int+ , id (id (negate (id 0))) :: Int+ , id (id (negate (id (id _)))) :: Int+ , id (id (negate (negate _))) :: Int+ , id (id (negate (abs _))) :: Int+ , id (id (negate (_ + _))) :: Int+ , id (id (negate (head _))) :: Int+ , id (id (negate (ord _))) :: Int+ , id (id (abs y)) :: Int+ , id (id (abs 1)) :: Int+ , id (id (abs (id x))) :: Int+ , id (id (abs (id 0))) :: Int+ , id (id (abs (id (id _)))) :: Int+ , id (id (abs (negate _))) :: Int+ , id (id (abs (abs _))) :: Int+ , id (id (abs (_ + _))) :: Int+ , id (id (abs (head _))) :: Int+ , id (id (abs (ord _))) :: Int+ , id (id (_ + y)) :: Int+ , id (id (_ + 1)) :: Int+ , id (id (_ + id x)) :: Int+ , id (id (_ + id 0)) :: Int+ , id (id (_ + id (id _))) :: Int+ , id (id (_ + negate _)) :: Int+ , id (id (_ + abs _)) :: Int+ , id (id (_ + (_ + _))) :: Int+ , id (id (_ + head _)) :: Int+ , id (id (_ + ord _)) :: Int+ , id (id (x + x)) :: Int+ , id (id (x + 0)) :: Int+ , id (id (x + id _)) :: Int+ , id (id (0 + x)) :: Int+ , id (id (0 + 0)) :: Int+ , id (id (0 + id _)) :: Int+ , id (id (id _ + x)) :: Int+ , id (id (id _ + 0)) :: Int+ , id (id (id _ + id _)) :: Int+ , id (id (_ * x)) :: Int+ , id (id (_ * 0)) :: Int+ , id (id (_ * id _)) :: Int+ , id (id (f x)) :: Int+ , id (id (f 0)) :: Int+ , id (id (f (id _))) :: Int+ , id (id (y + _)) :: Int+ , id (id (1 + _)) :: Int+ , id (id (id x + _)) :: Int+ , id (id (id 0 + _)) :: Int+ , id (id (id (id _) + _)) :: Int+ , id (id (negate _ + _)) :: Int+ , id (id (abs _ + _)) :: Int+ , id (id ((_ + _) + _)) :: Int+ , id (id (head _ + _)) :: Int+ , id (id (ord _ + _)) :: Int+ , id (id (x * _)) :: Int+ , id (id (0 * _)) :: Int+ , id (id (id _ * _)) :: Int+ , id (id (g _)) :: Int+ , id (id (head ys)) :: Int+ , id (id (head [0])) :: Int+ , id (id (head (_:xs))) :: Int+ , id (id (head [_])) :: Int+ , id (id (head (_:_:_))) :: Int+ , id (id (head (x:_))) :: Int+ , id (id (head (0:_))) :: Int+ , id (id (head (id _:_))) :: Int+ , id (id (head (tail _))) :: Int+ , id (id (head (_ ++ _))) :: Int+ , id (id (ord d)) :: Int+ , id (id (ord ' ')) :: Int+ , id (negate z) :: Int+ , id (negate (-1)) :: Int+ , id (negate (id y)) :: Int+ , id (negate (id 1)) :: Int+ , id (negate (id (id x))) :: Int+ , id (negate (id (id 0))) :: Int+ , id (negate (id (id (id _)))) :: Int+ , id (negate (id (negate _))) :: Int+ , id (negate (id (abs _))) :: Int+ , id (negate (id (_ + _))) :: Int+ , id (negate (id (head _))) :: Int+ , id (negate (id (ord _))) :: Int+ , id (negate (negate x)) :: Int+ , id (negate (negate 0)) :: Int+ , id (negate (negate (id _))) :: Int+ , id (negate (abs x)) :: Int+ , id (negate (abs 0)) :: Int+ , id (negate (abs (id _))) :: Int+ , id (negate (_ + x)) :: Int+ , id (negate (_ + 0)) :: Int+ , id (negate (_ + id _)) :: Int+ , id (negate (x + _)) :: Int+ , id (negate (0 + _)) :: Int+ , id (negate (id _ + _)) :: Int+ , id (negate (_ * _)) :: Int+ , id (negate (f _)) :: Int+ , id (negate (head xs)) :: Int+ , id (negate (head [])) :: Int+ , id (negate (head (_:_))) :: Int+ , id (negate (ord c)) :: Int+ , id (negate (ord 'a')) :: Int+ , id (abs z) :: Int+ , id (abs (-1)) :: Int+ , id (abs (id y)) :: Int+ , id (abs (id 1)) :: Int+ , id (abs (id (id x))) :: Int+ , id (abs (id (id 0))) :: Int+ , id (abs (id (id (id _)))) :: Int+ , id (abs (id (negate _))) :: Int+ , id (abs (id (abs _))) :: Int+ , id (abs (id (_ + _))) :: Int+ , id (abs (id (head _))) :: Int+ , id (abs (id (ord _))) :: Int+ , id (abs (negate x)) :: Int+ , id (abs (negate 0)) :: Int+ , id (abs (negate (id _))) :: Int+ , id (abs (abs x)) :: Int+ , id (abs (abs 0)) :: Int+ , id (abs (abs (id _))) :: Int+ , id (abs (_ + x)) :: Int+ , id (abs (_ + 0)) :: Int+ , id (abs (_ + id _)) :: Int+ , id (abs (x + _)) :: Int+ , id (abs (0 + _)) :: Int+ , id (abs (id _ + _)) :: Int+ , id (abs (_ * _)) :: Int+ , id (abs (f _)) :: Int+ , id (abs (head xs)) :: Int+ , id (abs (head [])) :: Int+ , id (abs (head (_:_))) :: Int+ , id (abs (ord c)) :: Int+ , id (abs (ord 'a')) :: Int+ , id (_ + z) :: Int+ , id (_ + (-1)) :: Int+ , id (_ + id y) :: Int+ , id (_ + id 1) :: Int+ , id (_ + id (id x)) :: Int+ , id (_ + id (id 0)) :: Int+ , id (_ + id (id (id _))) :: Int+ , id (_ + id (negate _)) :: Int+ , id (_ + id (abs _)) :: Int+ , id (_ + id (_ + _)) :: Int+ , id (_ + id (head _)) :: Int+ , id (_ + id (ord _)) :: Int+ , id (_ + negate x) :: Int+ , id (_ + negate 0) :: Int+ , id (_ + negate (id _)) :: Int+ , id (_ + abs x) :: Int+ , id (_ + abs 0) :: Int+ , id (_ + abs (id _)) :: Int+ , id (_ + (_ + x)) :: Int+ , id (_ + (_ + 0)) :: Int+ , id (_ + (_ + id _)) :: Int+ , id (_ + (x + _)) :: Int+ , id (_ + (0 + _)) :: Int+ , id (_ + (id _ + _)) :: Int+ , id (_ + _ * _) :: Int+ , id (_ + f _) :: Int+ , id (_ + head xs) :: Int+ , id (_ + head []) :: Int+ , id (_ + head (_:_)) :: Int+ , id (_ + ord c) :: Int+ , id (_ + ord 'a') :: Int+ , id (x + y) :: Int+ , id (x + 1) :: Int+ , id (x + id x) :: Int+ , id (x + id 0) :: Int+ , id (x + id (id _)) :: Int+ , id (x + negate _) :: Int+ , id (x + abs _) :: Int+ , id (x + (_ + _)) :: Int+ , id (x + head _) :: Int+ , id (x + ord _) :: Int+ , id (0 + y) :: Int+ , id (0 + 1) :: Int+ , id (0 + id x) :: Int+ , id (0 + id 0) :: Int+ , id (0 + id (id _)) :: Int+ , id (0 + negate _) :: Int+ , id (0 + abs _) :: Int+ , id (0 + (_ + _)) :: Int+ , id (0 + head _) :: Int+ , id (0 + ord _) :: Int+ , id (id _ + y) :: Int+ , id (id _ + 1) :: Int+ , id (id _ + id x) :: Int+ , id (id _ + id 0) :: Int+ , id (id _ + id (id _)) :: Int+ , id (id _ + negate _) :: Int+ , id (id _ + abs _) :: Int+ , id (id _ + (_ + _)) :: Int+ , id (id _ + head _) :: Int+ , id (id _ + ord _) :: Int+ , id (_ * y) :: Int+ , id (_ * 1) :: Int+ , id (_ * id x) :: Int+ , id (_ * id 0) :: Int+ , id (_ * id (id _)) :: Int+ , id (_ * negate _) :: Int+ , id (_ * abs _) :: Int+ , id (_ * (_ + _)) :: Int+ , id (_ * head _) :: Int+ , id (_ * ord _) :: Int+ , id (f y) :: Int+ , id (f 1) :: Int+ , id (f (id x)) :: Int+ , id (f (id 0)) :: Int+ , id (f (id (id _))) :: Int+ , id (f (negate _)) :: Int+ , id (f (abs _)) :: Int+ , id (f (_ + _)) :: Int+ , id (f (head _)) :: Int+ , id (f (ord _)) :: Int+ , id (y + x) :: Int+ , id (y + 0) :: Int+ , id (y + id _) :: Int+ , id (1 + x) :: Int+ , id (1 + 0) :: Int+ , id (1 + id _) :: Int+ , id (id x + x) :: Int+ , id (id x + 0) :: Int+ , id (id x + id _) :: Int+ , id (id 0 + x) :: Int+ , id (id 0 + 0) :: Int+ , id (id 0 + id _) :: Int+ , id (id (id _) + x) :: Int+ , id (id (id _) + 0) :: Int+ , id (id (id _) + id _) :: Int+ , id (negate _ + x) :: Int+ , id (negate _ + 0) :: Int+ , id (negate _ + id _) :: Int+ , id (abs _ + x) :: Int+ , id (abs _ + 0) :: Int+ , id (abs _ + id _) :: Int+ , id ((_ + _) + x) :: Int+ , id ((_ + _) + 0) :: Int+ , id ((_ + _) + id _) :: Int+ , id (head _ + x) :: Int+ , id (head _ + 0) :: Int+ , id (head _ + id _) :: Int+ , id (ord _ + x) :: Int+ , id (ord _ + 0) :: Int+ , id (ord _ + id _) :: Int+ , id (x * x) :: Int+ , id (x * 0) :: Int+ , id (x * id _) :: Int+ , id (0 * x) :: Int+ , id (0 * 0) :: Int+ , id (0 * id _) :: Int+ , id (id _ * x) :: Int+ , id (id _ * 0) :: Int+ , id (id _ * id _) :: Int+ , id (g x) :: Int+ , id (g 0) :: Int+ , id (g (id _)) :: Int+ , id (z + _) :: Int+ , id ((-1) + _) :: Int+ , id (id y + _) :: Int+ , id (id 1 + _) :: Int+ , id (id (id x) + _) :: Int+ , id (id (id 0) + _) :: Int+ , id (id (id (id _)) + _) :: Int+ , id (id (negate _) + _) :: Int+ , id (id (abs _) + _) :: Int+ , id (id (_ + _) + _) :: Int+ , id (id (head _) + _) :: Int+ , id (id (ord _) + _) :: Int+ , id (negate x + _) :: Int+ , id (negate 0 + _) :: Int+ , id (negate (id _) + _) :: Int+ , id (abs x + _) :: Int+ , id (abs 0 + _) :: Int+ , id (abs (id _) + _) :: Int+ , id ((_ + x) + _) :: Int+ , id ((_ + 0) + _) :: Int+ , id ((_ + id _) + _) :: Int+ , id ((x + _) + _) :: Int+ , id ((0 + _) + _) :: Int+ , id ((id _ + _) + _) :: Int+ , id (_ * _ + _) :: Int+ , id (f _ + _) :: Int+ , id (head xs + _) :: Int+ , id (head [] + _) :: Int+ , id (head (_:_) + _) :: Int+ , id (ord c + _) :: Int+ , id (ord 'a' + _) :: Int+ , id (y * _) :: Int+ , id (1 * _) :: Int+ , id (id x * _) :: Int+ , id (id 0 * _) :: Int+ , id (id (id _) * _) :: Int+ , id (negate _ * _) :: Int+ , id (abs _ * _) :: Int+ , id ((_ + _) * _) :: Int+ , id (head _ * _) :: Int+ , id (ord _ * _) :: Int+ , id (h _) :: Int+ , id (head zs) :: Int+ , id (head [0,0]) :: Int+ , id (head [1]) :: Int+ , id (head (_:ys)) :: Int+ , id (head [_,0]) :: Int+ , id (head (_:_:xs)) :: Int+ , id (head [_,_]) :: Int+ , id (head (_:_:_:_)) :: Int+ , id (head (_:x:_)) :: Int+ , id (head (_:0:_)) :: Int+ , id (head (_:id _:_)) :: Int+ , id (head (_:tail _)) :: Int+ , id (head (_:(_ ++ _))) :: Int+ , id (head (x:xs)) :: Int+ , id (head [x]) :: Int+ , id (head (x:_:_)) :: Int+ , id (head (0:xs)) :: Int+ , id (head [0]) :: Int+ , id (head (0:_:_)) :: Int+ , id (head (id _:xs)) :: Int+ , id (head [id _]) :: Int+ , id (head (id _:_:_)) :: Int+ , id (head (y:_)) :: Int+ , id (head (1:_)) :: Int+ , id (head (id x:_)) :: Int+ , id (head (id 0:_)) :: Int+ , id (head (id (id _):_)) :: Int+ , id (head (negate _:_)) :: Int+ , id (head (abs _:_)) :: Int+ , id (head (_ + _:_)) :: Int+ , id (head (head _:_)) :: Int+ , id (head (ord _:_)) :: Int+ , id (head (tail xs)) :: Int+ , id (head (tail [])) :: Int+ , id (head (tail (_:_))) :: Int+ , id (head (_ ++ xs)) :: Int+ , id (head (_ ++ [])) :: Int+ , id (head (_ ++ (_:_))) :: Int+ , id (head (xs ++ _)) :: Int+ , id (head ([] ++ _)) :: Int+ , id (head ((_:_) ++ _)) :: Int+ , id (head (sort _)) :: Int+ , id (head (insert _ _)) :: Int+ , id (ord e) :: Int+ , id (ord 'b') :: Int+ , negate x' :: Int+ , negate 2 :: Int+ , negate (id z) :: Int+ , negate (id (-1)) :: Int+ , negate (id (id y)) :: Int+ , negate (id (id 1)) :: Int+ , negate (id (id (id x))) :: Int+ , negate (id (id (id 0))) :: Int+ , negate (id (id (id (id _)))) :: Int+ , negate (id (id (negate _))) :: Int+ , negate (id (id (abs _))) :: Int+ , negate (id (id (_ + _))) :: Int+ , negate (id (id (head _))) :: Int+ , negate (id (id (ord _))) :: Int+ , negate (id (negate x)) :: Int+ , negate (id (negate 0)) :: Int+ , negate (id (negate (id _))) :: Int+ , negate (id (abs x)) :: Int+ , negate (id (abs 0)) :: Int+ , negate (id (abs (id _))) :: Int+ , negate (id (_ + x)) :: Int+ , negate (id (_ + 0)) :: Int+ , negate (id (_ + id _)) :: Int+ , negate (id (x + _)) :: Int+ , negate (id (0 + _)) :: Int+ , negate (id (id _ + _)) :: Int+ , negate (id (_ * _)) :: Int+ , negate (id (f _)) :: Int+ , negate (id (head xs)) :: Int+ , negate (id (head [])) :: Int+ , negate (id (head (_:_))) :: Int+ , negate (id (ord c)) :: Int+ , negate (id (ord 'a')) :: Int+ , negate (negate y) :: Int+ , negate (negate 1) :: Int+ , negate (negate (id x)) :: Int+ , negate (negate (id 0)) :: Int+ , negate (negate (id (id _))) :: Int+ , negate (negate (negate _)) :: Int+ , negate (negate (abs _)) :: Int+ , negate (negate (_ + _)) :: Int+ , negate (negate (head _)) :: Int+ , negate (negate (ord _)) :: Int+ , negate (abs y) :: Int+ , negate (abs 1) :: Int+ , negate (abs (id x)) :: Int+ , negate (abs (id 0)) :: Int+ , negate (abs (id (id _))) :: Int+ , negate (abs (negate _)) :: Int+ , negate (abs (abs _)) :: Int+ , negate (abs (_ + _)) :: Int+ , negate (abs (head _)) :: Int+ , negate (abs (ord _)) :: Int+ , negate (_ + y) :: Int+ , negate (_ + 1) :: Int+ , negate (_ + id x) :: Int+ , negate (_ + id 0) :: Int+ , negate (_ + id (id _)) :: Int+ , negate (_ + negate _) :: Int+ , negate (_ + abs _) :: Int+ , negate (_ + (_ + _)) :: Int+ , negate (_ + head _) :: Int+ , negate (_ + ord _) :: Int+ , negate (x + x) :: Int+ , negate (x + 0) :: Int+ , negate (x + id _) :: Int+ , negate (0 + x) :: Int+ , negate (0 + 0) :: Int+ , negate (0 + id _) :: Int+ , negate (id _ + x) :: Int+ , negate (id _ + 0) :: Int+ , negate (id _ + id _) :: Int+ , negate (_ * x) :: Int+ , negate (_ * 0) :: Int+ , negate (_ * id _) :: Int+ , negate (f x) :: Int+ , negate (f 0) :: Int+ , negate (f (id _)) :: Int+ , negate (y + _) :: Int+ , negate (1 + _) :: Int+ , negate (id x + _) :: Int+ , negate (id 0 + _) :: Int+ , negate (id (id _) + _) :: Int+ , negate (negate _ + _) :: Int+ , negate (abs _ + _) :: Int+ , negate ((_ + _) + _) :: Int+ , negate (head _ + _) :: Int+ , negate (ord _ + _) :: Int+ , negate (x * _) :: Int+ , negate (0 * _) :: Int+ , negate (id _ * _) :: Int+ , negate (g _) :: Int+ , negate (head ys) :: Int+ , negate (head [0]) :: Int+ , negate (head (_:xs)) :: Int+ , negate (head [_]) :: Int+ , negate (head (_:_:_)) :: Int+ , negate (head (x:_)) :: Int+ , negate (head (0:_)) :: Int+ , negate (head (id _:_)) :: Int+ , negate (head (tail _)) :: Int+ , negate (head (_ ++ _)) :: Int+ , negate (ord d) :: Int+ , negate (ord ' ') :: Int+ , abs x' :: Int+ , abs 2 :: Int+ , abs (id z) :: Int+ , abs (id (-1)) :: Int+ , abs (id (id y)) :: Int+ , abs (id (id 1)) :: Int+ , abs (id (id (id x))) :: Int+ , abs (id (id (id 0))) :: Int+ , abs (id (id (id (id _)))) :: Int+ , abs (id (id (negate _))) :: Int+ , abs (id (id (abs _))) :: Int+ , abs (id (id (_ + _))) :: Int+ , abs (id (id (head _))) :: Int+ , abs (id (id (ord _))) :: Int+ , abs (id (negate x)) :: Int+ , abs (id (negate 0)) :: Int+ , abs (id (negate (id _))) :: Int+ , abs (id (abs x)) :: Int+ , abs (id (abs 0)) :: Int+ , abs (id (abs (id _))) :: Int+ , abs (id (_ + x)) :: Int+ , abs (id (_ + 0)) :: Int+ , abs (id (_ + id _)) :: Int+ , abs (id (x + _)) :: Int+ , abs (id (0 + _)) :: Int+ , abs (id (id _ + _)) :: Int+ , abs (id (_ * _)) :: Int+ , abs (id (f _)) :: Int+ , abs (id (head xs)) :: Int+ , abs (id (head [])) :: Int+ , abs (id (head (_:_))) :: Int+ , abs (id (ord c)) :: Int+ , abs (id (ord 'a')) :: Int+ , abs (negate y) :: Int+ , abs (negate 1) :: Int+ , abs (negate (id x)) :: Int+ , abs (negate (id 0)) :: Int+ , abs (negate (id (id _))) :: Int+ , abs (negate (negate _)) :: Int+ , abs (negate (abs _)) :: Int+ , abs (negate (_ + _)) :: Int+ , abs (negate (head _)) :: Int+ , abs (negate (ord _)) :: Int+ , abs (abs y) :: Int+ , abs (abs 1) :: Int+ , abs (abs (id x)) :: Int+ , abs (abs (id 0)) :: Int+ , abs (abs (id (id _))) :: Int+ , abs (abs (negate _)) :: Int+ , abs (abs (abs _)) :: Int+ , abs (abs (_ + _)) :: Int+ , abs (abs (head _)) :: Int+ , abs (abs (ord _)) :: Int+ , abs (_ + y) :: Int+ , abs (_ + 1) :: Int+ , abs (_ + id x) :: Int+ , abs (_ + id 0) :: Int+ , abs (_ + id (id _)) :: Int+ , abs (_ + negate _) :: Int+ , abs (_ + abs _) :: Int+ , abs (_ + (_ + _)) :: Int+ , abs (_ + head _) :: Int+ , abs (_ + ord _) :: Int+ , abs (x + x) :: Int+ , abs (x + 0) :: Int+ , abs (x + id _) :: Int+ , abs (0 + x) :: Int+ , abs (0 + 0) :: Int+ , abs (0 + id _) :: Int+ , abs (id _ + x) :: Int+ , abs (id _ + 0) :: Int+ , abs (id _ + id _) :: Int+ , abs (_ * x) :: Int+ , abs (_ * 0) :: Int+ , abs (_ * id _) :: Int+ , abs (f x) :: Int+ , abs (f 0) :: Int+ , abs (f (id _)) :: Int+ , abs (y + _) :: Int+ , abs (1 + _) :: Int+ , abs (id x + _) :: Int+ , abs (id 0 + _) :: Int+ , abs (id (id _) + _) :: Int+ , abs (negate _ + _) :: Int+ , abs (abs _ + _) :: Int+ , abs ((_ + _) + _) :: Int+ , abs (head _ + _) :: Int+ , abs (ord _ + _) :: Int+ , abs (x * _) :: Int+ , abs (0 * _) :: Int+ , abs (id _ * _) :: Int+ , abs (g _) :: Int+ , abs (head ys) :: Int+ , abs (head [0]) :: Int+ , abs (head (_:xs)) :: Int+ , abs (head [_]) :: Int+ , abs (head (_:_:_)) :: Int+ , abs (head (x:_)) :: Int+ , abs (head (0:_)) :: Int+ , abs (head (id _:_)) :: Int+ , abs (head (tail _)) :: Int+ , abs (head (_ ++ _)) :: Int+ , abs (ord d) :: Int+ , abs (ord ' ') :: Int+ , _ + x' :: Int+ , _ + 2 :: Int+ , _ + id z :: Int+ , _ + id (-1) :: Int+ , _ + id (id y) :: Int+ , _ + id (id 1) :: Int+ , _ + id (id (id x)) :: Int+ , _ + id (id (id 0)) :: Int+ , _ + id (id (id (id _))) :: Int+ , _ + id (id (negate _)) :: Int+ , _ + id (id (abs _)) :: Int+ , _ + id (id (_ + _)) :: Int+ , _ + id (id (head _)) :: Int+ , _ + id (id (ord _)) :: Int+ , _ + id (negate x) :: Int+ , _ + id (negate 0) :: Int+ , _ + id (negate (id _)) :: Int+ , _ + id (abs x) :: Int+ , _ + id (abs 0) :: Int+ , _ + id (abs (id _)) :: Int+ , _ + id (_ + x) :: Int+ , _ + id (_ + 0) :: Int+ , _ + id (_ + id _) :: Int+ , _ + id (x + _) :: Int+ , _ + id (0 + _) :: Int+ , _ + id (id _ + _) :: Int+ , _ + id (_ * _) :: Int+ , _ + id (f _) :: Int+ , _ + id (head xs) :: Int+ , _ + id (head []) :: Int+ , _ + id (head (_:_)) :: Int+ , _ + id (ord c) :: Int+ , _ + id (ord 'a') :: Int+ , _ + negate y :: Int+ , _ + negate 1 :: Int+ , _ + negate (id x) :: Int+ , _ + negate (id 0) :: Int+ , _ + negate (id (id _)) :: Int+ , _ + negate (negate _) :: Int+ , _ + negate (abs _) :: Int+ , _ + negate (_ + _) :: Int+ , _ + negate (head _) :: Int+ , _ + negate (ord _) :: Int+ , _ + abs y :: Int+ , _ + abs 1 :: Int+ , _ + abs (id x) :: Int+ , _ + abs (id 0) :: Int+ , _ + abs (id (id _)) :: Int+ , _ + abs (negate _) :: Int+ , _ + abs (abs _) :: Int+ , _ + abs (_ + _) :: Int+ , _ + abs (head _) :: Int+ , _ + abs (ord _) :: Int+ , _ + (_ + y) :: Int+ , _ + (_ + 1) :: Int+ , _ + (_ + id x) :: Int+ , _ + (_ + id 0) :: Int+ , _ + (_ + id (id _)) :: Int+ , _ + (_ + negate _) :: Int+ , _ + (_ + abs _) :: Int+ , _ + (_ + (_ + _)) :: Int+ , _ + (_ + head _) :: Int+ , _ + (_ + ord _) :: Int+ , _ + (x + x) :: Int+ , _ + (x + 0) :: Int+ , _ + (x + id _) :: Int+ , _ + (0 + x) :: Int+ , _ + (0 + 0) :: Int+ , _ + (0 + id _) :: Int+ , _ + (id _ + x) :: Int+ , _ + (id _ + 0) :: Int+ , _ + (id _ + id _) :: Int+ , _ + _ * x :: Int+ , _ + _ * 0 :: Int+ , _ + _ * id _ :: Int+ , _ + f x :: Int+ , _ + f 0 :: Int+ , _ + f (id _) :: Int+ , _ + (y + _) :: Int+ , _ + (1 + _) :: Int+ , _ + (id x + _) :: Int+ , _ + (id 0 + _) :: Int+ , _ + (id (id _) + _) :: Int+ , _ + (negate _ + _) :: Int+ , _ + (abs _ + _) :: Int+ , _ + ((_ + _) + _) :: Int+ , _ + (head _ + _) :: Int+ , _ + (ord _ + _) :: Int+ , _ + x * _ :: Int+ , _ + 0 * _ :: Int+ , _ + id _ * _ :: Int+ , _ + g _ :: Int+ , _ + head ys :: Int+ , _ + head [0] :: Int+ , _ + head (_:xs) :: Int+ , _ + head [_] :: Int+ , _ + head (_:_:_) :: Int+ , _ + head (x:_) :: Int+ , _ + head (0:_) :: Int+ , _ + head (id _:_) :: Int+ , _ + head (tail _) :: Int+ , _ + head (_ ++ _) :: Int+ , _ + ord d :: Int+ , _ + ord ' ' :: Int+ , x + z :: Int+ , x + (-1) :: Int+ , x + id y :: Int+ , x + id 1 :: Int+ , x + id (id x) :: Int+ , x + id (id 0) :: Int+ , x + id (id (id _)) :: Int+ , x + id (negate _) :: Int+ , x + id (abs _) :: Int+ , x + id (_ + _) :: Int+ , x + id (head _) :: Int+ , x + id (ord _) :: Int+ , x + negate x :: Int+ , x + negate 0 :: Int+ , x + negate (id _) :: Int+ , x + abs x :: Int+ , x + abs 0 :: Int+ , x + abs (id _) :: Int+ , x + (_ + x) :: Int+ , x + (_ + 0) :: Int+ , x + (_ + id _) :: Int+ , x + (x + _) :: Int+ , x + (0 + _) :: Int+ , x + (id _ + _) :: Int+ , x + _ * _ :: Int+ , x + f _ :: Int+ , x + head xs :: Int+ , x + head [] :: Int+ , x + head (_:_) :: Int+ , x + ord c :: Int+ , x + ord 'a' :: Int+ , 0 + z :: Int+ , 0 + (-1) :: Int+ , 0 + id y :: Int+ , 0 + id 1 :: Int+ , 0 + id (id x) :: Int+ , 0 + id (id 0) :: Int+ , 0 + id (id (id _)) :: Int+ , 0 + id (negate _) :: Int+ , 0 + id (abs _) :: Int+ , 0 + id (_ + _) :: Int+ , 0 + id (head _) :: Int+ , 0 + id (ord _) :: Int+ , 0 + negate x :: Int+ , 0 + negate 0 :: Int+ , 0 + negate (id _) :: Int+ , 0 + abs x :: Int+ , 0 + abs 0 :: Int+ , 0 + abs (id _) :: Int+ , 0 + (_ + x) :: Int+ , 0 + (_ + 0) :: Int+ , 0 + (_ + id _) :: Int+ , 0 + (x + _) :: Int+ , 0 + (0 + _) :: Int+ , 0 + (id _ + _) :: Int+ , 0 + _ * _ :: Int+ , 0 + f _ :: Int+ , 0 + head xs :: Int+ , 0 + head [] :: Int+ , 0 + head (_:_) :: Int+ , 0 + ord c :: Int+ , 0 + ord 'a' :: Int+ , id _ + z :: Int+ , id _ + (-1) :: Int+ , id _ + id y :: Int+ , id _ + id 1 :: Int+ , id _ + id (id x) :: Int+ , id _ + id (id 0) :: Int+ , id _ + id (id (id _)) :: Int+ , id _ + id (negate _) :: Int+ , id _ + id (abs _) :: Int+ , id _ + id (_ + _) :: Int+ , id _ + id (head _) :: Int+ , id _ + id (ord _) :: Int+ , id _ + negate x :: Int+ , id _ + negate 0 :: Int+ , id _ + negate (id _) :: Int+ , id _ + abs x :: Int+ , id _ + abs 0 :: Int+ , id _ + abs (id _) :: Int+ , id _ + (_ + x) :: Int+ , id _ + (_ + 0) :: Int+ , id _ + (_ + id _) :: Int+ , id _ + (x + _) :: Int+ , id _ + (0 + _) :: Int+ , id _ + (id _ + _) :: Int+ , id _ + _ * _ :: Int+ , id _ + f _ :: Int+ , id _ + head xs :: Int+ , id _ + head [] :: Int+ , id _ + head (_:_) :: Int+ , id _ + ord c :: Int+ , id _ + ord 'a' :: Int+ , _ * z :: Int+ , _ * (-1) :: Int+ , _ * id y :: Int+ , _ * id 1 :: Int+ , _ * id (id x) :: Int+ , _ * id (id 0) :: Int+ , _ * id (id (id _)) :: Int+ , _ * id (negate _) :: Int+ , _ * id (abs _) :: Int+ , _ * id (_ + _) :: Int+ , _ * id (head _) :: Int+ , _ * id (ord _) :: Int+ , _ * negate x :: Int+ , _ * negate 0 :: Int+ , _ * negate (id _) :: Int+ , _ * abs x :: Int+ , _ * abs 0 :: Int+ , _ * abs (id _) :: Int+ , _ * (_ + x) :: Int+ , _ * (_ + 0) :: Int+ , _ * (_ + id _) :: Int+ , _ * (x + _) :: Int+ , _ * (0 + _) :: Int+ , _ * (id _ + _) :: Int+ , _ * (_ * _) :: Int+ , _ * f _ :: Int+ , _ * head xs :: Int+ , _ * head [] :: Int+ , _ * head (_:_) :: Int+ , _ * ord c :: Int+ , _ * ord 'a' :: Int+ , f z :: Int+ , f (-1) :: Int+ , f (id y) :: Int+ , f (id 1) :: Int+ , f (id (id x)) :: Int+ , f (id (id 0)) :: Int+ , f (id (id (id _))) :: Int+ , f (id (negate _)) :: Int+ , f (id (abs _)) :: Int+ , f (id (_ + _)) :: Int+ , f (id (head _)) :: Int+ , f (id (ord _)) :: Int+ , f (negate x) :: Int+ , f (negate 0) :: Int+ , f (negate (id _)) :: Int+ , f (abs x) :: Int+ , f (abs 0) :: Int+ , f (abs (id _)) :: Int+ , f (_ + x) :: Int+ , f (_ + 0) :: Int+ , f (_ + id _) :: Int+ , f (x + _) :: Int+ , f (0 + _) :: Int+ , f (id _ + _) :: Int+ , f (_ * _) :: Int+ , f (f _) :: Int+ , f (head xs) :: Int+ , f (head []) :: Int+ , f (head (_:_)) :: Int+ , f (ord c) :: Int+ , f (ord 'a') :: Int+ , y + y :: Int+ , y + 1 :: Int+ , y + id x :: Int+ , y + id 0 :: Int+ , y + id (id _) :: Int+ , y + negate _ :: Int+ , y + abs _ :: Int+ , y + (_ + _) :: Int+ , y + head _ :: Int+ , y + ord _ :: Int+ , 1 + y :: Int+ , 1 + 1 :: Int+ , 1 + id x :: Int+ , 1 + id 0 :: Int+ , 1 + id (id _) :: Int+ , 1 + negate _ :: Int+ , 1 + abs _ :: Int+ , 1 + (_ + _) :: Int+ , 1 + head _ :: Int+ , 1 + ord _ :: Int+ , id x + y :: Int+ , id x + 1 :: Int+ , id x + id x :: Int+ , id x + id 0 :: Int+ , id x + id (id _) :: Int+ , id x + negate _ :: Int+ , id x + abs _ :: Int+ , id x + (_ + _) :: Int+ , id x + head _ :: Int+ , id x + ord _ :: Int+ , id 0 + y :: Int+ , id 0 + 1 :: Int+ , id 0 + id x :: Int+ , id 0 + id 0 :: Int+ , id 0 + id (id _) :: Int+ , id 0 + negate _ :: Int+ , id 0 + abs _ :: Int+ , id 0 + (_ + _) :: Int+ , id 0 + head _ :: Int+ , id 0 + ord _ :: Int+ , id (id _) + y :: Int+ , id (id _) + 1 :: Int+ , id (id _) + id x :: Int+ , id (id _) + id 0 :: Int+ , id (id _) + id (id _) :: Int+ , id (id _) + negate _ :: Int+ , id (id _) + abs _ :: Int+ , id (id _) + (_ + _) :: Int+ , id (id _) + head _ :: Int+ , id (id _) + ord _ :: Int+ , negate _ + y :: Int+ , negate _ + 1 :: Int+ , negate _ + id x :: Int+ , negate _ + id 0 :: Int+ , negate _ + id (id _) :: Int+ , negate _ + negate _ :: Int+ , negate _ + abs _ :: Int+ , negate _ + (_ + _) :: Int+ , negate _ + head _ :: Int+ , negate _ + ord _ :: Int+ , abs _ + y :: Int+ , abs _ + 1 :: Int+ , abs _ + id x :: Int+ , abs _ + id 0 :: Int+ , abs _ + id (id _) :: Int+ , abs _ + negate _ :: Int+ , abs _ + abs _ :: Int+ , abs _ + (_ + _) :: Int+ , abs _ + head _ :: Int+ , abs _ + ord _ :: Int+ , (_ + _) + y :: Int+ , (_ + _) + 1 :: Int+ , (_ + _) + id x :: Int+ , (_ + _) + id 0 :: Int+ , (_ + _) + id (id _) :: Int+ , (_ + _) + negate _ :: Int+ , (_ + _) + abs _ :: Int+ , (_ + _) + (_ + _) :: Int+ , (_ + _) + head _ :: Int+ , (_ + _) + ord _ :: Int+ , head _ + y :: Int+ , head _ + 1 :: Int+ , head _ + id x :: Int+ , head _ + id 0 :: Int+ , head _ + id (id _) :: Int+ , head _ + negate _ :: Int+ , head _ + abs _ :: Int+ , head _ + (_ + _) :: Int+ , head _ + head _ :: Int+ , head _ + ord _ :: Int+ , ord _ + y :: Int+ , ord _ + 1 :: Int+ , ord _ + id x :: Int+ , ord _ + id 0 :: Int+ , ord _ + id (id _) :: Int+ , ord _ + negate _ :: Int+ , ord _ + abs _ :: Int+ , ord _ + (_ + _) :: Int+ , ord _ + head _ :: Int+ , ord _ + ord _ :: Int+ , x * y :: Int+ , x * 1 :: Int+ , x * id x :: Int+ , x * id 0 :: Int+ , x * id (id _) :: Int+ , x * negate _ :: Int+ , x * abs _ :: Int+ , x * (_ + _) :: Int+ , x * head _ :: Int+ , x * ord _ :: Int+ , 0 * y :: Int+ , 0 * 1 :: Int+ , 0 * id x :: Int+ , 0 * id 0 :: Int+ , 0 * id (id _) :: Int+ , 0 * negate _ :: Int+ , 0 * abs _ :: Int+ , 0 * (_ + _) :: Int+ , 0 * head _ :: Int+ , 0 * ord _ :: Int+ , id _ * y :: Int+ , id _ * 1 :: Int+ , id _ * id x :: Int+ , id _ * id 0 :: Int+ , id _ * id (id _) :: Int+ , id _ * negate _ :: Int+ , id _ * abs _ :: Int+ , id _ * (_ + _) :: Int+ , id _ * head _ :: Int+ , id _ * ord _ :: Int+ , g y :: Int+ , g 1 :: Int+ , g (id x) :: Int+ , g (id 0) :: Int+ , g (id (id _)) :: Int+ , g (negate _) :: Int+ , g (abs _) :: Int+ , g (_ + _) :: Int+ , g (head _) :: Int+ , g (ord _) :: Int+ , z + x :: Int+ , z + 0 :: Int+ , z + id _ :: Int+ , (-1) + x :: Int+ , (-1) + 0 :: Int+ , (-1) + id _ :: Int+ , id y + x :: Int+ , id y + 0 :: Int+ , id y + id _ :: Int+ , id 1 + x :: Int+ , id 1 + 0 :: Int+ , id 1 + id _ :: Int+ , id (id x) + x :: Int+ , id (id x) + 0 :: Int+ , id (id x) + id _ :: Int+ , id (id 0) + x :: Int+ , id (id 0) + 0 :: Int+ , id (id 0) + id _ :: Int+ , id (id (id _)) + x :: Int+ , id (id (id _)) + 0 :: Int+ , id (id (id _)) + id _ :: Int+ , id (negate _) + x :: Int+ , id (negate _) + 0 :: Int+ , id (negate _) + id _ :: Int+ , id (abs _) + x :: Int+ , id (abs _) + 0 :: Int+ , id (abs _) + id _ :: Int+ , id (_ + _) + x :: Int+ , id (_ + _) + 0 :: Int+ , id (_ + _) + id _ :: Int+ , id (head _) + x :: Int+ , id (head _) + 0 :: Int+ , id (head _) + id _ :: Int+ , id (ord _) + x :: Int+ , id (ord _) + 0 :: Int+ , id (ord _) + id _ :: Int+ , negate x + x :: Int+ , negate x + 0 :: Int+ , negate x + id _ :: Int+ , negate 0 + x :: Int+ , negate 0 + 0 :: Int+ , negate 0 + id _ :: Int+ , negate (id _) + x :: Int+ , negate (id _) + 0 :: Int+ , negate (id _) + id _ :: Int+ , abs x + x :: Int+ , abs x + 0 :: Int+ , abs x + id _ :: Int+ , abs 0 + x :: Int+ , abs 0 + 0 :: Int+ , abs 0 + id _ :: Int+ , abs (id _) + x :: Int+ , abs (id _) + 0 :: Int+ , abs (id _) + id _ :: Int+ , (_ + x) + x :: Int+ , (_ + x) + 0 :: Int+ , (_ + x) + id _ :: Int+ , (_ + 0) + x :: Int+ , (_ + 0) + 0 :: Int+ , (_ + 0) + id _ :: Int+ , (_ + id _) + x :: Int+ , (_ + id _) + 0 :: Int+ , (_ + id _) + id _ :: Int+ , (x + _) + x :: Int+ , (x + _) + 0 :: Int+ , (x + _) + id _ :: Int+ , (0 + _) + x :: Int+ , (0 + _) + 0 :: Int+ , (0 + _) + id _ :: Int+ , (id _ + _) + x :: Int+ , (id _ + _) + 0 :: Int+ , (id _ + _) + id _ :: Int+ , _ * _ + x :: Int+ , _ * _ + 0 :: Int+ , _ * _ + id _ :: Int+ , f _ + x :: Int+ , f _ + 0 :: Int+ , f _ + id _ :: Int+ , head xs + x :: Int+ , head xs + 0 :: Int+ , head xs + id _ :: Int+ , head [] + x :: Int+ , head [] + 0 :: Int+ , head [] + id _ :: Int+ , head (_:_) + x :: Int+ , head (_:_) + 0 :: Int+ , head (_:_) + id _ :: Int+ , ord c + x :: Int+ , ord c + 0 :: Int+ , ord c + id _ :: Int+ , ord 'a' + x :: Int+ , ord 'a' + 0 :: Int+ , ord 'a' + id _ :: Int+ , y * x :: Int+ , y * 0 :: Int+ , y * id _ :: Int+ , 1 * x :: Int+ , 1 * 0 :: Int+ , 1 * id _ :: Int+ , id x * x :: Int+ , id x * 0 :: Int+ , id x * id _ :: Int+ , id 0 * x :: Int+ , id 0 * 0 :: Int+ , id 0 * id _ :: Int+ , id (id _) * x :: Int+ , id (id _) * 0 :: Int+ , id (id _) * id _ :: Int+ , negate _ * x :: Int+ , negate _ * 0 :: Int+ , negate _ * id _ :: Int+ , abs _ * x :: Int+ , abs _ * 0 :: Int+ , abs _ * id _ :: Int+ , (_ + _) * x :: Int+ , (_ + _) * 0 :: Int+ , (_ + _) * id _ :: Int+ , head _ * x :: Int+ , head _ * 0 :: Int+ , head _ * id _ :: Int+ , ord _ * x :: Int+ , ord _ * 0 :: Int+ , ord _ * id _ :: Int+ , h x :: Int+ , h 0 :: Int+ , h (id _) :: Int+ , x' + _ :: Int+ , 2 + _ :: Int+ , id z + _ :: Int+ , id (-1) + _ :: Int+ , id (id y) + _ :: Int+ , id (id 1) + _ :: Int+ , id (id (id x)) + _ :: Int+ , id (id (id 0)) + _ :: Int+ , id (id (id (id _))) + _ :: Int+ , id (id (negate _)) + _ :: Int+ , id (id (abs _)) + _ :: Int+ , id (id (_ + _)) + _ :: Int+ , id (id (head _)) + _ :: Int+ , id (id (ord _)) + _ :: Int+ , id (negate x) + _ :: Int+ , id (negate 0) + _ :: Int+ , id (negate (id _)) + _ :: Int+ , id (abs x) + _ :: Int+ , id (abs 0) + _ :: Int+ , id (abs (id _)) + _ :: Int+ , id (_ + x) + _ :: Int+ , id (_ + 0) + _ :: Int+ , id (_ + id _) + _ :: Int+ , id (x + _) + _ :: Int+ , id (0 + _) + _ :: Int+ , id (id _ + _) + _ :: Int+ , id (_ * _) + _ :: Int+ , id (f _) + _ :: Int+ , id (head xs) + _ :: Int+ , id (head []) + _ :: Int+ , id (head (_:_)) + _ :: Int+ , id (ord c) + _ :: Int+ , id (ord 'a') + _ :: Int+ , negate y + _ :: Int+ , negate 1 + _ :: Int+ , negate (id x) + _ :: Int+ , negate (id 0) + _ :: Int+ , negate (id (id _)) + _ :: Int+ , negate (negate _) + _ :: Int+ , negate (abs _) + _ :: Int+ , negate (_ + _) + _ :: Int+ , negate (head _) + _ :: Int+ , negate (ord _) + _ :: Int+ , abs y + _ :: Int+ , abs 1 + _ :: Int+ , abs (id x) + _ :: Int+ , abs (id 0) + _ :: Int+ , abs (id (id _)) + _ :: Int+ , abs (negate _) + _ :: Int+ , abs (abs _) + _ :: Int+ , abs (_ + _) + _ :: Int+ , abs (head _) + _ :: Int+ , abs (ord _) + _ :: Int+ , (_ + y) + _ :: Int+ , (_ + 1) + _ :: Int+ , (_ + id x) + _ :: Int+ , (_ + id 0) + _ :: Int+ , (_ + id (id _)) + _ :: Int+ , (_ + negate _) + _ :: Int+ , (_ + abs _) + _ :: Int+ , (_ + (_ + _)) + _ :: Int+ , (_ + head _) + _ :: Int+ , (_ + ord _) + _ :: Int+ , (x + x) + _ :: Int+ , (x + 0) + _ :: Int+ , (x + id _) + _ :: Int+ , (0 + x) + _ :: Int+ , (0 + 0) + _ :: Int+ , (0 + id _) + _ :: Int+ , (id _ + x) + _ :: Int+ , (id _ + 0) + _ :: Int+ , (id _ + id _) + _ :: Int+ , _ * x + _ :: Int+ , _ * 0 + _ :: Int+ , _ * id _ + _ :: Int+ , f x + _ :: Int+ , f 0 + _ :: Int+ , f (id _) + _ :: Int+ , (y + _) + _ :: Int+ , (1 + _) + _ :: Int+ , (id x + _) + _ :: Int+ , (id 0 + _) + _ :: Int+ , (id (id _) + _) + _ :: Int+ , (negate _ + _) + _ :: Int+ , (abs _ + _) + _ :: Int+ , ((_ + _) + _) + _ :: Int+ , (head _ + _) + _ :: Int+ , (ord _ + _) + _ :: Int+ , x * _ + _ :: Int+ , 0 * _ + _ :: Int+ , id _ * _ + _ :: Int+ , g _ + _ :: Int+ , head ys + _ :: Int+ , head [0] + _ :: Int+ , head (_:xs) + _ :: Int+ , head [_] + _ :: Int+ , head (_:_:_) + _ :: Int+ , head (x:_) + _ :: Int+ , head (0:_) + _ :: Int+ , head (id _:_) + _ :: Int+ , head (tail _) + _ :: Int+ , head (_ ++ _) + _ :: Int+ , ord d + _ :: Int+ , ord ' ' + _ :: Int+ , z * _ :: Int+ , (-1) * _ :: Int+ , id y * _ :: Int+ , id 1 * _ :: Int+ , id (id x) * _ :: Int+ , id (id 0) * _ :: Int+ , id (id (id _)) * _ :: Int+ , id (negate _) * _ :: Int+ , id (abs _) * _ :: Int+ , id (_ + _) * _ :: Int+ , id (head _) * _ :: Int+ , id (ord _) * _ :: Int+ , negate x * _ :: Int+ , negate 0 * _ :: Int+ , negate (id _) * _ :: Int+ , abs x * _ :: Int+ , abs 0 * _ :: Int+ , abs (id _) * _ :: Int+ , (_ + x) * _ :: Int+ , (_ + 0) * _ :: Int+ , (_ + id _) * _ :: Int+ , (x + _) * _ :: Int+ , (0 + _) * _ :: Int+ , (id _ + _) * _ :: Int+ , (_ * _) * _ :: Int+ , f _ * _ :: Int+ , head xs * _ :: Int+ , head [] * _ :: Int+ , head (_:_) * _ :: Int+ , ord c * _ :: Int+ , ord 'a' * _ :: Int+ , f' _ :: Int+ , head xs' :: Int+ , head [0,0,0] :: Int+ , head [0,1] :: Int+ , head [1,0] :: Int+ , head [-1] :: Int+ , head (_:zs) :: Int+ , head [_,0,0] :: Int+ , head [_,1] :: Int+ , head (_:_:ys) :: Int+ , head [_,_,0] :: Int+ , head (_:_:_:xs) :: Int+ , head [_,_,_] :: Int+ , head (_:_:_:_:_) :: Int+ , head (_:_:x:_) :: Int+ , head (_:_:0:_) :: Int+ , head (_:_:id _:_) :: Int+ , head (_:_:tail _) :: Int+ , head (_:_:(_ ++ _)) :: Int+ , head (_:x:xs) :: Int+ , head [_,x] :: Int+ , head (_:x:_:_) :: Int+ , head (_:0:xs) :: Int+ , head [_,0] :: Int+ , head (_:0:_:_) :: Int+ , head (_:id _:xs) :: Int+ , head [_,id _] :: Int+ , head (_:id _:_:_) :: Int+ , head (_:y:_) :: Int+ , head (_:1:_) :: Int+ , head (_:id x:_) :: Int+ , head (_:id 0:_) :: Int+ , head (_:id (id _):_) :: Int+ , head (_:negate _:_) :: Int+ , head (_:abs _:_) :: Int+ , head (_:_ + _:_) :: Int+ , head (_:head _:_) :: Int+ , head (_:ord _:_) :: Int+ , head (_:tail xs) :: Int+ , head (_:tail []) :: Int+ , head (_:tail (_:_)) :: Int+ , head (_:(_ ++ xs)) :: Int+ , head (_:(_ ++ [])) :: Int+ , head (_:(_ ++ (_:_))) :: Int+ , head (_:(xs ++ _)) :: Int+ , head (_:([] ++ _)) :: Int+ , head (_:((_:_) ++ _)) :: Int+ , head (_:sort _) :: Int+ , head (_:insert _ _) :: Int+ , head (x:ys) :: Int+ , head [x,0] :: Int+ , head (x:_:xs) :: Int+ , head [x,_] :: Int+ , head (x:_:_:_) :: Int+ , head (x:x:_) :: Int+ , head (x:0:_) :: Int+ , head (x:id _:_) :: Int+ , head (x:tail _) :: Int+ , head (x:(_ ++ _)) :: Int+ , head (0:ys) :: Int+ , head [0,0] :: Int+ , head (0:_:xs) :: Int+ , head [0,_] :: Int+ , head (0:_:_:_) :: Int+ , head (0:x:_) :: Int+ , head (0:0:_) :: Int+ , head (0:id _:_) :: Int+ , head (0:tail _) :: Int+ , head (0:(_ ++ _)) :: Int+ , head (id _:ys) :: Int+ , head [id _,0] :: Int+ , head (id _:_:xs) :: Int+ , head [id _,_] :: Int+ , head (id _:_:_:_) :: Int+ , head (id _:x:_) :: Int+ , head (id _:0:_) :: Int+ , head (id _:id _:_) :: Int+ , head (id _:tail _) :: Int+ , head (id _:(_ ++ _)) :: Int+ , head (y:xs) :: Int+ , head [y] :: Int+ , head (y:_:_) :: Int+ , head (1:xs) :: Int+ , head [1] :: Int+ , head (1:_:_) :: Int+ , head (id x:xs) :: Int+ , head [id x] :: Int+ , head (id x:_:_) :: Int+ , head (id 0:xs) :: Int+ , head [id 0] :: Int+ , head (id 0:_:_) :: Int+ , head (id (id _):xs) :: Int+ , head [id (id _)] :: Int+ , head (id (id _):_:_) :: Int+ , head (negate _:xs) :: Int+ , head [negate _] :: Int+ , head (negate _:_:_) :: Int+ , head (abs _:xs) :: Int+ , head [abs _] :: Int+ , head (abs _:_:_) :: Int+ , head (_ + _:xs) :: Int+ , head [_ + _] :: Int+ , head (_ + _:_:_) :: Int+ , head (head _:xs) :: Int+ , head [head _] :: Int+ , head (head _:_:_) :: Int+ , head (ord _:xs) :: Int+ , head [ord _] :: Int+ , head (ord _:_:_) :: Int+ , head (z:_) :: Int+ , head ((-1):_) :: Int+ , head (id y:_) :: Int+ , head (id 1:_) :: Int+ , head (id (id x):_) :: Int+ , head (id (id 0):_) :: Int+ , head (id (id (id _)):_) :: Int+ , head (id (negate _):_) :: Int+ , head (id (abs _):_) :: Int+ , head (id (_ + _):_) :: Int+ , head (id (head _):_) :: Int+ , head (id (ord _):_) :: Int+ , head (negate x:_) :: Int+ , head (negate 0:_) :: Int+ , head (negate (id _):_) :: Int+ , head (abs x:_) :: Int+ , head (abs 0:_) :: Int+ , head (abs (id _):_) :: Int+ , head (_ + x:_) :: Int+ , head (_ + 0:_) :: Int+ , head (_ + id _:_) :: Int+ , head (x + _:_) :: Int+ , head (0 + _:_) :: Int+ , head (id _ + _:_) :: Int+ , head (_ * _:_) :: Int+ , head (f _:_) :: Int+ , head (head xs:_) :: Int+ , head (head []:_) :: Int+ , head (head (_:_):_) :: Int+ , head (ord c:_) :: Int+ , head (ord 'a':_) :: Int+ , head (tail ys) :: Int+ , head (tail [0]) :: Int+ , head (tail (_:xs)) :: Int+ , head (tail [_]) :: Int+ , head (tail (_:_:_)) :: Int+ , head (tail (x:_)) :: Int+ , head (tail (0:_)) :: Int+ , head (tail (id _:_)) :: Int+ , head (tail (tail _)) :: Int+ , head (tail (_ ++ _)) :: Int+ , head (_ ++ ys) :: Int+ , head (_ ++ [0]) :: Int+ , head (_ ++ (_:xs)) :: Int+ , head (_ ++ [_]) :: Int+ , head (_ ++ (_:_:_)) :: Int+ , head (_ ++ (x:_)) :: Int+ , head (_ ++ (0:_)) :: Int+ , head (_ ++ (id _:_)) :: Int+ , head (_ ++ tail _) :: Int+ , head (_ ++ (_ ++ _)) :: Int+ , head (xs ++ xs) :: Int+ , head (xs ++ []) :: Int+ , head (xs ++ (_:_)) :: Int+ , head ([] ++ xs) :: Int+ , head ([] ++ []) :: Int+ , head ([] ++ (_:_)) :: Int+ , head ((_:_) ++ xs) :: Int+ , head ((_:_) ++ []) :: Int+ , head ((_:_) ++ (_:_)) :: Int+ , head (ys ++ _) :: Int+ , head ([0] ++ _) :: Int+ , head ((_:xs) ++ _) :: Int+ , head ([_] ++ _) :: Int+ , head ((_:_:_) ++ _) :: Int+ , head ((x:_) ++ _) :: Int+ , head ((0:_) ++ _) :: Int+ , head ((id _:_) ++ _) :: Int+ , head (tail _ ++ _) :: Int+ , head ((_ ++ _) ++ _) :: Int+ , head (sort xs) :: Int+ , head (sort []) :: Int+ , head (sort (_:_)) :: Int+ , head (insert _ xs) :: Int+ , head (insert _ []) :: Int+ , head (insert _ (_:_)) :: Int+ , head (insert x _) :: Int+ , head (insert 0 _) :: Int+ , head (insert (id _) _) :: Int+ , ord c' :: Int+ , ord 'A' :: Int+ , q' :: Bool+ , not p' :: Bool+ , not (not r) :: Bool+ , not (not (not q)) :: Bool+ , not (not (not (not p))) :: Bool+ , not (not (not (not False))) :: Bool+ , not (not (not (not True))) :: Bool+ , not (not (not (not (not _)))) :: Bool+ , not (not (not (_ || _))) :: Bool+ , not (not (_ || p)) :: Bool+ , not (not (_ || False)) :: Bool+ , not (not (_ || True)) :: Bool+ , not (not (_ || not _)) :: Bool+ , not (not (p || _)) :: Bool+ , not (not (False || _)) :: Bool+ , not (not (True || _)) :: Bool+ , not (not (not _ || _)) :: Bool+ , not (not (_ && _)) :: Bool+ , not (not (_ == _)) :: Bool+ , not (not (_ == _)) :: Bool+ , not (not (odd _)) :: Bool+ , not (not (even _)) :: Bool+ , not (not (elem _ _)) :: Bool+ , not (_ || q) :: Bool+ , not (_ || not p) :: Bool+ , not (_ || not False) :: Bool+ , not (_ || not True) :: Bool+ , not (_ || not (not _)) :: Bool+ , not (_ || (_ || _)) :: Bool+ , not (p || p) :: Bool+ , not (p || False) :: Bool+ , not (p || True) :: Bool+ , not (p || not _) :: Bool+ , not (False || p) :: Bool+ , not (False || False) :: Bool+ , not (False || True) :: Bool+ , not (False || not _) :: Bool+ , not (True || p) :: Bool+ , not (True || False) :: Bool+ , not (True || True) :: Bool+ , not (True || not _) :: Bool+ , not (not _ || p) :: Bool+ , not (not _ || False) :: Bool+ , not (not _ || True) :: Bool+ , not (not _ || not _) :: Bool+ , not (_ && p) :: Bool+ , not (_ && False) :: Bool+ , not (_ && True) :: Bool+ , not (_ && not _) :: Bool+ , not (q || _) :: Bool+ , not (not p || _) :: Bool+ , not (not False || _) :: Bool+ , not (not True || _) :: Bool+ , not (not (not _) || _) :: Bool+ , not ((_ || _) || _) :: Bool+ , not (p && _) :: Bool+ , not (False && _) :: Bool+ , not (True && _) :: Bool+ , not (not _ && _) :: Bool+ , not (_ ==> _) :: Bool+ , not (_ == x) :: Bool+ , not (_ == 0) :: Bool+ , not (_ == id _) :: Bool+ , not (x == _) :: Bool+ , not (0 == _) :: Bool+ , not (id _ == _) :: Bool+ , not (_ == p) :: Bool+ , not (_ == False) :: Bool+ , not (_ == True) :: Bool+ , not (_ == not _) :: Bool+ , not (p == _) :: Bool+ , not (False == _) :: Bool+ , not (True == _) :: Bool+ , not (not _ == _) :: Bool+ , not (_ <= _) :: Bool+ , not (_ <= _) :: Bool+ , not (odd x) :: Bool+ , not (odd 0) :: Bool+ , not (odd (id _)) :: Bool+ , not (even x) :: Bool+ , not (even 0) :: Bool+ , not (even (id _)) :: Bool+ , not (elem _ xs) :: Bool+ , not (elem _ []) :: Bool+ , not (elem _ (_:_)) :: Bool+ , not (elem x _) :: Bool+ , not (elem 0 _) :: Bool+ , not (elem (id _) _) :: Bool+ , _ || r :: Bool+ , _ || not q :: Bool+ , _ || not (not p) :: Bool+ , _ || not (not False) :: Bool+ , _ || not (not True) :: Bool+ , _ || not (not (not _)) :: Bool+ , _ || not (_ || _) :: Bool+ , _ || (_ || p) :: Bool+ , _ || (_ || False) :: Bool+ , _ || (_ || True) :: Bool+ , _ || (_ || not _) :: Bool+ , _ || (p || _) :: Bool+ , _ || (False || _) :: Bool+ , _ || (True || _) :: Bool+ , _ || (not _ || _) :: Bool+ , _ || _ && _ :: Bool+ , _ || _ == _ :: Bool+ , _ || _ == _ :: Bool+ , _ || odd _ :: Bool+ , _ || even _ :: Bool+ , _ || elem _ _ :: Bool+ , p || q :: Bool+ , p || not p :: Bool+ , p || not False :: Bool+ , p || not True :: Bool+ , p || not (not _) :: Bool+ , p || (_ || _) :: Bool+ , False || q :: Bool+ , False || not p :: Bool+ , False || not False :: Bool+ , False || not True :: Bool+ , False || not (not _) :: Bool+ , False || (_ || _) :: Bool+ , True || q :: Bool+ , True || not p :: Bool+ , True || not False :: Bool+ , True || not True :: Bool+ , True || not (not _) :: Bool+ , True || (_ || _) :: Bool+ , not _ || q :: Bool+ , not _ || not p :: Bool+ , not _ || not False :: Bool+ , not _ || not True :: Bool+ , not _ || not (not _) :: Bool+ , not _ || (_ || _) :: Bool+ , _ && q :: Bool+ , _ && not p :: Bool+ , _ && not False :: Bool+ , _ && not True :: Bool+ , _ && not (not _) :: Bool+ , _ && (_ || _) :: Bool+ , q || p :: Bool+ , q || False :: Bool+ , q || True :: Bool+ , q || not _ :: Bool+ , not p || p :: Bool+ , not p || False :: Bool+ , not p || True :: Bool+ , not p || not _ :: Bool+ , not False || p :: Bool+ , not False || False :: Bool+ , not False || True :: Bool+ , not False || not _ :: Bool+ , not True || p :: Bool+ , not True || False :: Bool+ , not True || True :: Bool+ , not True || not _ :: Bool+ , not (not _) || p :: Bool+ , not (not _) || False :: Bool+ , not (not _) || True :: Bool+ , not (not _) || not _ :: Bool+ , (_ || _) || p :: Bool+ , (_ || _) || False :: Bool+ , (_ || _) || True :: Bool+ , (_ || _) || not _ :: Bool+ , p && p :: Bool+ , p && False :: Bool+ , p && True :: Bool+ , p && not _ :: Bool+ , False && p :: Bool+ , False && False :: Bool+ , False && True :: Bool+ , False && not _ :: Bool+ , True && p :: Bool+ , True && False :: Bool+ , True && True :: Bool+ , True && not _ :: Bool+ , not _ && p :: Bool+ , not _ && False :: Bool+ , not _ && True :: Bool+ , not _ && not _ :: Bool+ , _ ==> p :: Bool+ , _ ==> False :: Bool+ , _ ==> True :: Bool+ , _ ==> not _ :: Bool+ , r || _ :: Bool+ , not q || _ :: Bool+ , not (not p) || _ :: Bool+ , not (not False) || _ :: Bool+ , not (not True) || _ :: Bool+ , not (not (not _)) || _ :: Bool+ , not (_ || _) || _ :: Bool+ , (_ || p) || _ :: Bool+ , (_ || False) || _ :: Bool+ , (_ || True) || _ :: Bool+ , (_ || not _) || _ :: Bool+ , (p || _) || _ :: Bool+ , (False || _) || _ :: Bool+ , (True || _) || _ :: Bool+ , (not _ || _) || _ :: Bool+ , _ && _ || _ :: Bool+ , _ == _ || _ :: Bool+ , _ == _ || _ :: Bool+ , odd _ || _ :: Bool+ , even _ || _ :: Bool+ , elem _ _ || _ :: Bool+ , q && _ :: Bool+ , not p && _ :: Bool+ , not False && _ :: Bool+ , not True && _ :: Bool+ , not (not _) && _ :: Bool+ , (_ || _) && _ :: Bool+ , p ==> _ :: Bool+ , False ==> _ :: Bool+ , True ==> _ :: Bool+ , not _ ==> _ :: Bool+ , _ == y :: Bool+ , _ == 1 :: Bool+ , _ == id x :: Bool+ , _ == id 0 :: Bool+ , _ == id (id _) :: Bool+ , _ == negate _ :: Bool+ , _ == abs _ :: Bool+ , _ == _ + _ :: Bool+ , _ == head _ :: Bool+ , _ == ord _ :: Bool+ , x == x :: Bool+ , x == 0 :: Bool+ , x == id _ :: Bool+ , 0 == x :: Bool+ , 0 == 0 :: Bool+ , 0 == id _ :: Bool+ , id _ == x :: Bool+ , id _ == 0 :: Bool+ , id _ == id _ :: Bool+ , y == _ :: Bool+ , 1 == _ :: Bool+ , id x == _ :: Bool+ , id 0 == _ :: Bool+ , id (id _) == _ :: Bool+ , negate _ == _ :: Bool+ , abs _ == _ :: Bool+ , _ + _ == _ :: Bool+ , head _ == _ :: Bool+ , ord _ == _ :: Bool+ , _ == q :: Bool+ , _ == not p :: Bool+ , _ == not False :: Bool+ , _ == not True :: Bool+ , _ == not (not _) :: Bool+ , _ == (_ || _) :: Bool+ , p == p :: Bool+ , p == False :: Bool+ , p == True :: Bool+ , p == not _ :: Bool+ , False == p :: Bool+ , False == False :: Bool+ , False == True :: Bool+ , False == not _ :: Bool+ , True == p :: Bool+ , True == False :: Bool+ , True == True :: Bool+ , True == not _ :: Bool+ , not _ == p :: Bool+ , not _ == False :: Bool+ , not _ == True :: Bool+ , not _ == not _ :: Bool+ , q == _ :: Bool+ , not p == _ :: Bool+ , not False == _ :: Bool+ , not True == _ :: Bool+ , not (not _) == _ :: Bool+ , (_ || _) == _ :: Bool+ , _ <= x :: Bool+ , _ <= 0 :: Bool+ , _ <= id _ :: Bool+ , x <= _ :: Bool+ , 0 <= _ :: Bool+ , id _ <= _ :: Bool+ , _ <= p :: Bool+ , _ <= False :: Bool+ , _ <= True :: Bool+ , _ <= not _ :: Bool+ , p <= _ :: Bool+ , False <= _ :: Bool+ , True <= _ :: Bool+ , not _ <= _ :: Bool+ , _ < _ :: Bool+ , _ < _ :: Bool+ , odd y :: Bool+ , odd 1 :: Bool+ , odd (id x) :: Bool+ , odd (id 0) :: Bool+ , odd (id (id _)) :: Bool+ , odd (negate _) :: Bool+ , odd (abs _) :: Bool+ , odd (_ + _) :: Bool+ , odd (head _) :: Bool+ , odd (ord _) :: Bool+ , even y :: Bool+ , even 1 :: Bool+ , even (id x) :: Bool+ , even (id 0) :: Bool+ , even (id (id _)) :: Bool+ , even (negate _) :: Bool+ , even (abs _) :: Bool+ , even (_ + _) :: Bool+ , even (head _) :: Bool+ , even (ord _) :: Bool+ , elem _ ys :: Bool+ , elem _ [0] :: Bool+ , elem _ (_:xs) :: Bool+ , elem _ [_] :: Bool+ , elem _ (_:_:_) :: Bool+ , elem _ (x:_) :: Bool+ , elem _ (0:_) :: Bool+ , elem _ (id _:_) :: Bool+ , elem _ (tail _) :: Bool+ , elem _ (_ ++ _) :: Bool+ , elem x xs :: Bool+ , elem x [] :: Bool+ , elem x (_:_) :: Bool+ , elem 0 xs :: Bool+ , elem 0 [] :: Bool+ , elem 0 (_:_) :: Bool+ , elem (id _) xs :: Bool+ , elem (id _) [] :: Bool+ , elem (id _) (_:_) :: Bool+ , elem y _ :: Bool+ , elem 1 _ :: Bool+ , elem (id x) _ :: Bool+ , elem (id 0) _ :: Bool+ , elem (id (id _)) _ :: Bool+ , elem (negate _) _ :: Bool+ , elem (abs _) _ :: Bool+ , elem (_ + _) _ :: Bool+ , elem (head _) _ :: Bool+ , elem (ord _) _ :: Bool+ , d' :: Char+ , 'c' :: Char+ , ys' :: [Int]+ , [0,0,0,0] :: [Int]+ , [0,0,1] :: [Int]+ , [0,1,0] :: [Int]+ , [0,-1] :: [Int]+ , [1,0,0] :: [Int]+ , [1,1] :: [Int]+ , [-1,0] :: [Int]+ , [2] :: [Int]+ , _:xs' :: [Int]+ , [_,0,0,0] :: [Int]+ , [_,0,1] :: [Int]+ , [_,1,0] :: [Int]+ , [_,-1] :: [Int]+ , _:_:zs :: [Int]+ , [_,_,0,0] :: [Int]+ , [_,_,1] :: [Int]+ , _:_:_:ys :: [Int]+ , [_,_,_,0] :: [Int]+ , _:_:_:_:xs :: [Int]+ , [_,_,_,_] :: [Int]+ , _:_:_:_:_:_ :: [Int]+ , _:_:_:x:_ :: [Int]+ , _:_:_:0:_ :: [Int]+ , _:_:_:id _:_ :: [Int]+ , _:_:_:tail _ :: [Int]+ , _:_:_:(_ ++ _) :: [Int]+ , _:_:x:xs :: [Int]+ , [_,_,x] :: [Int]+ , _:_:x:_:_ :: [Int]+ , _:_:0:xs :: [Int]+ , [_,_,0] :: [Int]+ , _:_:0:_:_ :: [Int]+ , _:_:id _:xs :: [Int]+ , [_,_,id _] :: [Int]+ , _:_:id _:_:_ :: [Int]+ , _:_:y:_ :: [Int]+ , _:_:1:_ :: [Int]+ , _:_:id x:_ :: [Int]+ , _:_:id 0:_ :: [Int]+ , _:_:id (id _):_ :: [Int]+ , _:_:negate _:_ :: [Int]+ , _:_:abs _:_ :: [Int]+ , _:_:_ + _:_ :: [Int]+ , _:_:head _:_ :: [Int]+ , _:_:ord _:_ :: [Int]+ , _:_:tail xs :: [Int]+ , _:_:tail [] :: [Int]+ , _:_:tail (_:_) :: [Int]+ , _:_:(_ ++ xs) :: [Int]+ , _:_:(_ ++ []) :: [Int]+ , _:_:(_ ++ (_:_)) :: [Int]+ , _:_:(xs ++ _) :: [Int]+ , [_,_,] ++ _ :: [Int]+ , _:_:((_:_) ++ _) :: [Int]+ , _:_:sort _ :: [Int]+ , _:_:insert _ _ :: [Int]+ , _:x:ys :: [Int]+ , [_,x,0] :: [Int]+ , _:x:_:xs :: [Int]+ , [_,x,_] :: [Int]+ , _:x:_:_:_ :: [Int]+ , _:x:x:_ :: [Int]+ , _:x:0:_ :: [Int]+ , _:x:id _:_ :: [Int]+ , _:x:tail _ :: [Int]+ , _:x:(_ ++ _) :: [Int]+ , _:0:ys :: [Int]+ , [_,0,0] :: [Int]+ , _:0:_:xs :: [Int]+ , [_,0,_] :: [Int]+ , _:0:_:_:_ :: [Int]+ , _:0:x:_ :: [Int]+ , _:0:0:_ :: [Int]+ , _:0:id _:_ :: [Int]+ , _:0:tail _ :: [Int]+ , _:0:(_ ++ _) :: [Int]+ , _:id _:ys :: [Int]+ , [_,id _,0] :: [Int]+ , _:id _:_:xs :: [Int]+ , [_,id _,_] :: [Int]+ , _:id _:_:_:_ :: [Int]+ , _:id _:x:_ :: [Int]+ , _:id _:0:_ :: [Int]+ , _:id _:id _:_ :: [Int]+ , _:id _:tail _ :: [Int]+ , _:id _:(_ ++ _) :: [Int]+ , _:y:xs :: [Int]+ , [_,y] :: [Int]+ , _:y:_:_ :: [Int]+ , _:1:xs :: [Int]+ , [_,1] :: [Int]+ , _:1:_:_ :: [Int]+ , _:id x:xs :: [Int]+ , [_,id x] :: [Int]+ , _:id x:_:_ :: [Int]+ , _:id 0:xs :: [Int]+ , [_,id 0] :: [Int]+ , _:id 0:_:_ :: [Int]+ , _:id (id _):xs :: [Int]+ , [_,id (id _)] :: [Int]+ , _:id (id _):_:_ :: [Int]+ , _:negate _:xs :: [Int]+ , [_,negate _] :: [Int]+ , _:negate _:_:_ :: [Int]+ , _:abs _:xs :: [Int]+ , [_,abs _] :: [Int]+ , _:abs _:_:_ :: [Int]+ , _:_ + _:xs :: [Int]+ , [_,_ + _] :: [Int]+ , _:_ + _:_:_ :: [Int]+ , _:head _:xs :: [Int]+ , [_,head _] :: [Int]+ , _:head _:_:_ :: [Int]+ , _:ord _:xs :: [Int]+ , [_,ord _] :: [Int]+ , _:ord _:_:_ :: [Int]+ , _:z:_ :: [Int]+ , _:(-1):_ :: [Int]+ , _:id y:_ :: [Int]+ , _:id 1:_ :: [Int]+ , _:id (id x):_ :: [Int]+ , _:id (id 0):_ :: [Int]+ , _:id (id (id _)):_ :: [Int]+ , _:id (negate _):_ :: [Int]+ , _:id (abs _):_ :: [Int]+ , _:id (_ + _):_ :: [Int]+ , _:id (head _):_ :: [Int]+ , _:id (ord _):_ :: [Int]+ , _:negate x:_ :: [Int]+ , _:negate 0:_ :: [Int]+ , _:negate (id _):_ :: [Int]+ , _:abs x:_ :: [Int]+ , _:abs 0:_ :: [Int]+ , _:abs (id _):_ :: [Int]+ , _:_ + x:_ :: [Int]+ , _:_ + 0:_ :: [Int]+ , _:_ + id _:_ :: [Int]+ , _:x + _:_ :: [Int]+ , _:0 + _:_ :: [Int]+ , _:id _ + _:_ :: [Int]+ , _:_ * _:_ :: [Int]+ , _:f _:_ :: [Int]+ , _:head xs:_ :: [Int]+ , _:head []:_ :: [Int]+ , _:head (_:_):_ :: [Int]+ , _:ord c:_ :: [Int]+ , _:ord 'a':_ :: [Int]+ , _:tail ys :: [Int]+ , _:tail [0] :: [Int]+ , _:tail (_:xs) :: [Int]+ , _:tail [_] :: [Int]+ , _:tail (_:_:_) :: [Int]+ , _:tail (x:_) :: [Int]+ , _:tail (0:_) :: [Int]+ , _:tail (id _:_) :: [Int]+ , _:tail (tail _) :: [Int]+ , _:tail (_ ++ _) :: [Int]+ , _:(_ ++ ys) :: [Int]+ , _:(_ ++ [0]) :: [Int]+ , _:(_ ++ (_:xs)) :: [Int]+ , _:(_ ++ [_]) :: [Int]+ , _:(_ ++ (_:_:_)) :: [Int]+ , _:(_ ++ (x:_)) :: [Int]+ , _:(_ ++ (0:_)) :: [Int]+ , _:(_ ++ (id _:_)) :: [Int]+ , _:(_ ++ tail _) :: [Int]+ , _:(_ ++ (_ ++ _)) :: [Int]+ , _:(xs ++ xs) :: [Int]+ , _:(xs ++ []) :: [Int]+ , _:(xs ++ (_:_)) :: [Int]+ , _:([] ++ xs) :: [Int]+ , _:([] ++ []) :: [Int]+ , _:([] ++ (_:_)) :: [Int]+ , _:((_:_) ++ xs) :: [Int]+ , _:((_:_) ++ []) :: [Int]+ , _:((_:_) ++ (_:_)) :: [Int]+ , _:(ys ++ _) :: [Int]+ , _:([0] ++ _) :: [Int]+ , _:((_:xs) ++ _) :: [Int]+ , _:([_] ++ _) :: [Int]+ , _:((_:_:_) ++ _) :: [Int]+ , _:((x:_) ++ _) :: [Int]+ , _:((0:_) ++ _) :: [Int]+ , _:((id _:_) ++ _) :: [Int]+ , _:(tail _ ++ _) :: [Int]+ , _:((_ ++ _) ++ _) :: [Int]+ , _:sort xs :: [Int]+ , _:sort [] :: [Int]+ , _:sort (_:_) :: [Int]+ , _:insert _ xs :: [Int]+ , _:insert _ [] :: [Int]+ , _:insert _ (_:_) :: [Int]+ , _:insert x _ :: [Int]+ , _:insert 0 _ :: [Int]+ , _:insert (id _) _ :: [Int]+ , x:zs :: [Int]+ , [x,0,0] :: [Int]+ , [x,1] :: [Int]+ , x:_:ys :: [Int]+ , [x,_,0] :: [Int]+ , x:_:_:xs :: [Int]+ , [x,_,_] :: [Int]+ , x:_:_:_:_ :: [Int]+ , x:_:x:_ :: [Int]+ , x:_:0:_ :: [Int]+ , x:_:id _:_ :: [Int]+ , x:_:tail _ :: [Int]+ , x:_:(_ ++ _) :: [Int]+ , x:x:xs :: [Int]+ , [x,x] :: [Int]+ , x:x:_:_ :: [Int]+ , x:0:xs :: [Int]+ , [x,0] :: [Int]+ , x:0:_:_ :: [Int]+ , x:id _:xs :: [Int]+ , [x,id _] :: [Int]+ , x:id _:_:_ :: [Int]+ , x:y:_ :: [Int]+ , x:1:_ :: [Int]+ , x:id x:_ :: [Int]+ , x:id 0:_ :: [Int]+ , x:id (id _):_ :: [Int]+ , x:negate _:_ :: [Int]+ , x:abs _:_ :: [Int]+ , x:_ + _:_ :: [Int]+ , x:head _:_ :: [Int]+ , x:ord _:_ :: [Int]+ , x:tail xs :: [Int]+ , x:tail [] :: [Int]+ , x:tail (_:_) :: [Int]+ , x:(_ ++ xs) :: [Int]+ , x:(_ ++ []) :: [Int]+ , x:(_ ++ (_:_)) :: [Int]+ , x:(xs ++ _) :: [Int]+ , x:([] ++ _) :: [Int]+ , x:((_:_) ++ _) :: [Int]+ , x:sort _ :: [Int]+ , x:insert _ _ :: [Int]+ , 0:zs :: [Int]+ , [0,0,0] :: [Int]+ , [0,1] :: [Int]+ , 0:_:ys :: [Int]+ , [0,_,0] :: [Int]+ , 0:_:_:xs :: [Int]+ , [0,_,_] :: [Int]+ , 0:_:_:_:_ :: [Int]+ , 0:_:x:_ :: [Int]+ , 0:_:0:_ :: [Int]+ , 0:_:id _:_ :: [Int]+ , 0:_:tail _ :: [Int]+ , 0:_:(_ ++ _) :: [Int]+ , 0:x:xs :: [Int]+ , [0,x] :: [Int]+ , 0:x:_:_ :: [Int]+ , 0:0:xs :: [Int]+ , [0,0] :: [Int]+ , 0:0:_:_ :: [Int]+ , 0:id _:xs :: [Int]+ , [0,id _] :: [Int]+ , 0:id _:_:_ :: [Int]+ , 0:y:_ :: [Int]+ , 0:1:_ :: [Int]+ , 0:id x:_ :: [Int]+ , 0:id 0:_ :: [Int]+ , 0:id (id _):_ :: [Int]+ , 0:negate _:_ :: [Int]+ , 0:abs _:_ :: [Int]+ , 0:_ + _:_ :: [Int]+ , 0:head _:_ :: [Int]+ , 0:ord _:_ :: [Int]+ , 0:tail xs :: [Int]+ , 0:tail [] :: [Int]+ , 0:tail (_:_) :: [Int]+ , 0:(_ ++ xs) :: [Int]+ , 0:(_ ++ []) :: [Int]+ , 0:(_ ++ (_:_)) :: [Int]+ , 0:(xs ++ _) :: [Int]+ , 0:([] ++ _) :: [Int]+ , 0:((_:_) ++ _) :: [Int]+ , 0:sort _ :: [Int]+ , 0:insert _ _ :: [Int]+ , id _:zs :: [Int]+ , [id _,0,0] :: [Int]+ , [id _,1] :: [Int]+ , id _:_:ys :: [Int]+ , [id _,_,0] :: [Int]+ , id _:_:_:xs :: [Int]+ , [id _,_,_] :: [Int]+ , id _:_:_:_:_ :: [Int]+ , id _:_:x:_ :: [Int]+ , id _:_:0:_ :: [Int]+ , id _:_:id _:_ :: [Int]+ , id _:_:tail _ :: [Int]+ , id _:_:(_ ++ _) :: [Int]+ , id _:x:xs :: [Int]+ , [id _,x] :: [Int]+ , id _:x:_:_ :: [Int]+ , id _:0:xs :: [Int]+ , [id _,0] :: [Int]+ , id _:0:_:_ :: [Int]+ , id _:id _:xs :: [Int]+ , [id _,id _] :: [Int]+ , id _:id _:_:_ :: [Int]+ , id _:y:_ :: [Int]+ , id _:1:_ :: [Int]+ , id _:id x:_ :: [Int]+ , id _:id 0:_ :: [Int]+ , id _:id (id _):_ :: [Int]+ , id _:negate _:_ :: [Int]+ , id _:abs _:_ :: [Int]+ , id _:_ + _:_ :: [Int]+ , id _:head _:_ :: [Int]+ , id _:ord _:_ :: [Int]+ , id _:tail xs :: [Int]+ , id _:tail [] :: [Int]+ , id _:tail (_:_) :: [Int]+ , id _:(_ ++ xs) :: [Int]+ , id _:(_ ++ []) :: [Int]+ , id _:(_ ++ (_:_)) :: [Int]+ , id _:(xs ++ _) :: [Int]+ , id _:([] ++ _) :: [Int]+ , id _:((_:_) ++ _) :: [Int]+ , id _:sort _ :: [Int]+ , id _:insert _ _ :: [Int]+ , y:ys :: [Int]+ , [y,0] :: [Int]+ , y:_:xs :: [Int]+ , [y,_] :: [Int]+ , y:_:_:_ :: [Int]+ , y:x:_ :: [Int]+ , y:0:_ :: [Int]+ , y:id _:_ :: [Int]+ , y:tail _ :: [Int]+ , y:(_ ++ _) :: [Int]+ , 1:ys :: [Int]+ , [1,0] :: [Int]+ , 1:_:xs :: [Int]+ , [1,_] :: [Int]+ , 1:_:_:_ :: [Int]+ , 1:x:_ :: [Int]+ , 1:0:_ :: [Int]+ , 1:id _:_ :: [Int]+ , 1:tail _ :: [Int]+ , 1:(_ ++ _) :: [Int]+ , id x:ys :: [Int]+ , [id x,0] :: [Int]+ , id x:_:xs :: [Int]+ , [id x,_] :: [Int]+ , id x:_:_:_ :: [Int]+ , id x:x:_ :: [Int]+ , id x:0:_ :: [Int]+ , id x:id _:_ :: [Int]+ , id x:tail _ :: [Int]+ , id x:(_ ++ _) :: [Int]+ , id 0:ys :: [Int]+ , [id 0,0] :: [Int]+ , id 0:_:xs :: [Int]+ , [id 0,_] :: [Int]+ , id 0:_:_:_ :: [Int]+ , id 0:x:_ :: [Int]+ , id 0:0:_ :: [Int]+ , id 0:id _:_ :: [Int]+ , id 0:tail _ :: [Int]+ , id 0:(_ ++ _) :: [Int]+ , id (id _):ys :: [Int]+ , [id (id _),0] :: [Int]+ , id (id _):_:xs :: [Int]+ , [id (id _),_] :: [Int]+ , id (id _):_:_:_ :: [Int]+ , id (id _):x:_ :: [Int]+ , id (id _):0:_ :: [Int]+ , id (id _):id _:_ :: [Int]+ , id (id _):tail _ :: [Int]+ , id (id _):(_ ++ _) :: [Int]+ , negate _:ys :: [Int]+ , [negate _,0] :: [Int]+ , negate _:_:xs :: [Int]+ , [negate _,_] :: [Int]+ , negate _:_:_:_ :: [Int]+ , negate _:x:_ :: [Int]+ , negate _:0:_ :: [Int]+ , negate _:id _:_ :: [Int]+ , negate _:tail _ :: [Int]+ , negate _:(_ ++ _) :: [Int]+ , abs _:ys :: [Int]+ , [abs _,0] :: [Int]+ , abs _:_:xs :: [Int]+ , [abs _,_] :: [Int]+ , abs _:_:_:_ :: [Int]+ , abs _:x:_ :: [Int]+ , abs _:0:_ :: [Int]+ , abs _:id _:_ :: [Int]+ , abs _:tail _ :: [Int]+ , abs _:(_ ++ _) :: [Int]+ , _ + _:ys :: [Int]+ , [_ + _,0] :: [Int]+ , _ + _:_:xs :: [Int]+ , [_ + _,_] :: [Int]+ , _ + _:_:_:_ :: [Int]+ , _ + _:x:_ :: [Int]+ , _ + _:0:_ :: [Int]+ , _ + _:id _:_ :: [Int]+ , _ + _:tail _ :: [Int]+ , _ + _:(_ ++ _) :: [Int]+ , head _:ys :: [Int]+ , [head _,0] :: [Int]+ , head _:_:xs :: [Int]+ , [head _,_] :: [Int]+ , head _:_:_:_ :: [Int]+ , head _:x:_ :: [Int]+ , head _:0:_ :: [Int]+ , head _:id _:_ :: [Int]+ , head _:tail _ :: [Int]+ , head _:(_ ++ _) :: [Int]+ , ord _:ys :: [Int]+ , [ord _,0] :: [Int]+ , ord _:_:xs :: [Int]+ , [ord _,_] :: [Int]+ , ord _:_:_:_ :: [Int]+ , ord _:x:_ :: [Int]+ , ord _:0:_ :: [Int]+ , ord _:id _:_ :: [Int]+ , ord _:tail _ :: [Int]+ , ord _:(_ ++ _) :: [Int]+ , z:xs :: [Int]+ , [z] :: [Int]+ , z:_:_ :: [Int]+ , (-1):xs :: [Int]+ , [-1] :: [Int]+ , (-1):_:_ :: [Int]+ , id y:xs :: [Int]+ , [id y] :: [Int]+ , id y:_:_ :: [Int]+ , id 1:xs :: [Int]+ , [id 1] :: [Int]+ , id 1:_:_ :: [Int]+ , id (id x):xs :: [Int]+ , [id (id x)] :: [Int]+ , id (id x):_:_ :: [Int]+ , id (id 0):xs :: [Int]+ , [id (id 0)] :: [Int]+ , id (id 0):_:_ :: [Int]+ , id (id (id _)):xs :: [Int]+ , [id (id (id _))] :: [Int]+ , id (id (id _)):_:_ :: [Int]+ , id (negate _):xs :: [Int]+ , [id (negate _)] :: [Int]+ , id (negate _):_:_ :: [Int]+ , id (abs _):xs :: [Int]+ , [id (abs _)] :: [Int]+ , id (abs _):_:_ :: [Int]+ , id (_ + _):xs :: [Int]+ , [id (_ + _)] :: [Int]+ , id (_ + _):_:_ :: [Int]+ , id (head _):xs :: [Int]+ , [id (head _)] :: [Int]+ , id (head _):_:_ :: [Int]+ , id (ord _):xs :: [Int]+ , [id (ord _)] :: [Int]+ , id (ord _):_:_ :: [Int]+ , negate x:xs :: [Int]+ , [negate x] :: [Int]+ , negate x:_:_ :: [Int]+ , negate 0:xs :: [Int]+ , [negate 0] :: [Int]+ , negate 0:_:_ :: [Int]+ , negate (id _):xs :: [Int]+ , [negate (id _)] :: [Int]+ , negate (id _):_:_ :: [Int]+ , abs x:xs :: [Int]+ , [abs x] :: [Int]+ , abs x:_:_ :: [Int]+ , abs 0:xs :: [Int]+ , [abs 0] :: [Int]+ , abs 0:_:_ :: [Int]+ , abs (id _):xs :: [Int]+ , [abs (id _)] :: [Int]+ , abs (id _):_:_ :: [Int]+ , _ + x:xs :: [Int]+ , [_ + x] :: [Int]+ , _ + x:_:_ :: [Int]+ , _ + 0:xs :: [Int]+ , [_ + 0] :: [Int]+ , _ + 0:_:_ :: [Int]+ , _ + id _:xs :: [Int]+ , [_ + id _] :: [Int]+ , _ + id _:_:_ :: [Int]+ , x + _:xs :: [Int]+ , [x + _] :: [Int]+ , x + _:_:_ :: [Int]+ , 0 + _:xs :: [Int]+ , [0 + _] :: [Int]+ , 0 + _:_:_ :: [Int]+ , id _ + _:xs :: [Int]+ , [id _ + _] :: [Int]+ , id _ + _:_:_ :: [Int]+ , _ * _:xs :: [Int]+ , [_ * _] :: [Int]+ , _ * _:_:_ :: [Int]+ , f _:xs :: [Int]+ , [f _] :: [Int]+ , f _:_:_ :: [Int]+ , head xs:xs :: [Int]+ , [head xs] :: [Int]+ , head xs:_:_ :: [Int]+ , head []:xs :: [Int]+ , [head []] :: [Int]+ , head []:_:_ :: [Int]+ , head (_:_):xs :: [Int]+ , [head (_:_)] :: [Int]+ , head (_:_):_:_ :: [Int]+ , ord c:xs :: [Int]+ , [ord c] :: [Int]+ , ord c:_:_ :: [Int]+ , ord 'a':xs :: [Int]+ , [ord 'a'] :: [Int]+ , ord 'a':_:_ :: [Int]+ , x':_ :: [Int]+ , 2:_ :: [Int]+ , id z:_ :: [Int]+ , id (-1):_ :: [Int]+ , id (id y):_ :: [Int]+ , id (id 1):_ :: [Int]+ , id (id (id x)):_ :: [Int]+ , id (id (id 0)):_ :: [Int]+ , id (id (id (id _))):_ :: [Int]+ , id (id (negate _)):_ :: [Int]+ , id (id (abs _)):_ :: [Int]+ , id (id (_ + _)):_ :: [Int]+ , id (id (head _)):_ :: [Int]+ , id (id (ord _)):_ :: [Int]+ , id (negate x):_ :: [Int]+ , id (negate 0):_ :: [Int]+ , id (negate (id _)):_ :: [Int]+ , id (abs x):_ :: [Int]+ , id (abs 0):_ :: [Int]+ , id (abs (id _)):_ :: [Int]+ , id (_ + x):_ :: [Int]+ , id (_ + 0):_ :: [Int]+ , id (_ + id _):_ :: [Int]+ , id (x + _):_ :: [Int]+ , id (0 + _):_ :: [Int]+ , id (id _ + _):_ :: [Int]+ , id (_ * _):_ :: [Int]+ , id (f _):_ :: [Int]+ , id (head xs):_ :: [Int]+ , id (head []):_ :: [Int]+ , id (head (_:_)):_ :: [Int]+ , id (ord c):_ :: [Int]+ , id (ord 'a'):_ :: [Int]+ , negate y:_ :: [Int]+ , negate 1:_ :: [Int]+ , negate (id x):_ :: [Int]+ , negate (id 0):_ :: [Int]+ , negate (id (id _)):_ :: [Int]+ , negate (negate _):_ :: [Int]+ , negate (abs _):_ :: [Int]+ , negate (_ + _):_ :: [Int]+ , negate (head _):_ :: [Int]+ , negate (ord _):_ :: [Int]+ , abs y:_ :: [Int]+ , abs 1:_ :: [Int]+ , abs (id x):_ :: [Int]+ , abs (id 0):_ :: [Int]+ , abs (id (id _)):_ :: [Int]+ , abs (negate _):_ :: [Int]+ , abs (abs _):_ :: [Int]+ , abs (_ + _):_ :: [Int]+ , abs (head _):_ :: [Int]+ , abs (ord _):_ :: [Int]+ , _ + y:_ :: [Int]+ , _ + 1:_ :: [Int]+ , _ + id x:_ :: [Int]+ , _ + id 0:_ :: [Int]+ , _ + id (id _):_ :: [Int]+ , _ + negate _:_ :: [Int]+ , _ + abs _:_ :: [Int]+ , _ + (_ + _):_ :: [Int]+ , _ + head _:_ :: [Int]+ , _ + ord _:_ :: [Int]+ , x + x:_ :: [Int]+ , x + 0:_ :: [Int]+ , x + id _:_ :: [Int]+ , 0 + x:_ :: [Int]+ , 0 + 0:_ :: [Int]+ , 0 + id _:_ :: [Int]+ , id _ + x:_ :: [Int]+ , id _ + 0:_ :: [Int]+ , id _ + id _:_ :: [Int]+ , _ * x:_ :: [Int]+ , _ * 0:_ :: [Int]+ , _ * id _:_ :: [Int]+ , f x:_ :: [Int]+ , f 0:_ :: [Int]+ , f (id _):_ :: [Int]+ , y + _:_ :: [Int]+ , 1 + _:_ :: [Int]+ , id x + _:_ :: [Int]+ , id 0 + _:_ :: [Int]+ , id (id _) + _:_ :: [Int]+ , negate _ + _:_ :: [Int]+ , abs _ + _:_ :: [Int]+ , (_ + _) + _:_ :: [Int]+ , head _ + _:_ :: [Int]+ , ord _ + _:_ :: [Int]+ , x * _:_ :: [Int]+ , 0 * _:_ :: [Int]+ , id _ * _:_ :: [Int]+ , g _:_ :: [Int]+ , head ys:_ :: [Int]+ , head [0]:_ :: [Int]+ , head (_:xs):_ :: [Int]+ , head [_]:_ :: [Int]+ , head (_:_:_):_ :: [Int]+ , head (x:_):_ :: [Int]+ , head (0:_):_ :: [Int]+ , head (id _:_):_ :: [Int]+ , head (tail _):_ :: [Int]+ , head (_ ++ _):_ :: [Int]+ , ord d:_ :: [Int]+ , ord ' ':_ :: [Int]+ , tail zs :: [Int]+ , tail [0,0] :: [Int]+ , tail [1] :: [Int]+ , tail (_:ys) :: [Int]+ , tail [_,0] :: [Int]+ , tail (_:_:xs) :: [Int]+ , tail [_,_] :: [Int]+ , tail (_:_:_:_) :: [Int]+ , tail (_:x:_) :: [Int]+ , tail (_:0:_) :: [Int]+ , tail (_:id _:_) :: [Int]+ , tail (_:tail _) :: [Int]+ , tail (_:(_ ++ _)) :: [Int]+ , tail (x:xs) :: [Int]+ , tail [x] :: [Int]+ , tail (x:_:_) :: [Int]+ , tail (0:xs) :: [Int]+ , tail [0] :: [Int]+ , tail (0:_:_) :: [Int]+ , tail (id _:xs) :: [Int]+ , tail [id _] :: [Int]+ , tail (id _:_:_) :: [Int]+ , tail (y:_) :: [Int]+ , tail (1:_) :: [Int]+ , tail (id x:_) :: [Int]+ , tail (id 0:_) :: [Int]+ , tail (id (id _):_) :: [Int]+ , tail (negate _:_) :: [Int]+ , tail (abs _:_) :: [Int]+ , tail (_ + _:_) :: [Int]+ , tail (head _:_) :: [Int]+ , tail (ord _:_) :: [Int]+ , tail (tail xs) :: [Int]+ , tail (tail []) :: [Int]+ , tail (tail (_:_)) :: [Int]+ , tail (_ ++ xs) :: [Int]+ , tail (_ ++ []) :: [Int]+ , tail (_ ++ (_:_)) :: [Int]+ , tail (xs ++ _) :: [Int]+ , tail ([] ++ _) :: [Int]+ , tail ((_:_) ++ _) :: [Int]+ , tail (sort _) :: [Int]+ , tail (insert _ _) :: [Int]+ , _ ++ zs :: [Int]+ , _ ++ [0,0] :: [Int]+ , _ ++ [1] :: [Int]+ , _ ++ (_:ys) :: [Int]+ , _ ++ [_,0] :: [Int]+ , _ ++ (_:_:xs) :: [Int]+ , _ ++ [_,_] :: [Int]+ , _ ++ (_:_:_:_) :: [Int]+ , _ ++ (_:x:_) :: [Int]+ , _ ++ (_:0:_) :: [Int]+ , _ ++ (_:id _:_) :: [Int]+ , _ ++ (_:tail _) :: [Int]+ , _ ++ (_:(_ ++ _)) :: [Int]+ , _ ++ (x:xs) :: [Int]+ , _ ++ [x] :: [Int]+ , _ ++ (x:_:_) :: [Int]+ , _ ++ (0:xs) :: [Int]+ , _ ++ [0] :: [Int]+ , _ ++ (0:_:_) :: [Int]+ , _ ++ (id _:xs) :: [Int]+ , _ ++ [id _] :: [Int]+ , _ ++ (id _:_:_) :: [Int]+ , _ ++ (y:_) :: [Int]+ , _ ++ (1:_) :: [Int]+ , _ ++ (id x:_) :: [Int]+ , _ ++ (id 0:_) :: [Int]+ , _ ++ (id (id _):_) :: [Int]+ , _ ++ (negate _:_) :: [Int]+ , _ ++ (abs _:_) :: [Int]+ , _ ++ (_ + _:_) :: [Int]+ , _ ++ (head _:_) :: [Int]+ , _ ++ (ord _:_) :: [Int]+ , _ ++ tail xs :: [Int]+ , _ ++ tail [] :: [Int]+ , _ ++ tail (_:_) :: [Int]+ , _ ++ (_ ++ xs) :: [Int]+ , _ ++ (_ ++ []) :: [Int]+ , _ ++ (_ ++ (_:_)) :: [Int]+ , _ ++ (xs ++ _) :: [Int]+ , _ ++ ([] ++ _) :: [Int]+ , _ ++ ((_:_) ++ _) :: [Int]+ , _ ++ sort _ :: [Int]+ , _ ++ insert _ _ :: [Int]+ , xs ++ ys :: [Int]+ , xs ++ [0] :: [Int]+ , xs ++ (_:xs) :: [Int]+ , xs ++ [_] :: [Int]+ , xs ++ (_:_:_) :: [Int]+ , xs ++ (x:_) :: [Int]+ , xs ++ (0:_) :: [Int]+ , xs ++ (id _:_) :: [Int]+ , xs ++ tail _ :: [Int]+ , xs ++ (_ ++ _) :: [Int]+ , [] ++ ys :: [Int]+ , [] ++ [0] :: [Int]+ , [] ++ (_:xs) :: [Int]+ , [] ++ [_] :: [Int]+ , [] ++ (_:_:_) :: [Int]+ , [] ++ (x:_) :: [Int]+ , [] ++ (0:_) :: [Int]+ , [] ++ (id _:_) :: [Int]+ , [] ++ tail _ :: [Int]+ , [] ++ (_ ++ _) :: [Int]+ , (_:_) ++ ys :: [Int]+ , (_:_) ++ [0] :: [Int]+ , (_:_) ++ (_:xs) :: [Int]+ , (_:_) ++ [_] :: [Int]+ , (_:_) ++ (_:_:_) :: [Int]+ , (_:_) ++ (x:_) :: [Int]+ , (_:_) ++ (0:_) :: [Int]+ , (_:_) ++ (id _:_) :: [Int]+ , (_:_) ++ tail _ :: [Int]+ , (_:_) ++ (_ ++ _) :: [Int]+ , ys ++ xs :: [Int]+ , ys ++ [] :: [Int]+ , ys ++ (_:_) :: [Int]+ , [0] ++ xs :: [Int]+ , [0] ++ [] :: [Int]+ , [0] ++ (_:_) :: [Int]+ , (_:xs) ++ xs :: [Int]+ , (_:xs) ++ [] :: [Int]+ , (_:xs) ++ (_:_) :: [Int]+ , [_] ++ xs :: [Int]+ , [_] ++ [] :: [Int]+ , [_] ++ (_:_) :: [Int]+ , (_:_:_) ++ xs :: [Int]+ , (_:_:_) ++ [] :: [Int]+ , (_:_:_) ++ (_:_) :: [Int]+ , (x:_) ++ xs :: [Int]+ , (x:_) ++ [] :: [Int]+ , (x:_) ++ (_:_) :: [Int]+ , (0:_) ++ xs :: [Int]+ , (0:_) ++ [] :: [Int]+ , (0:_) ++ (_:_) :: [Int]+ , (id _:_) ++ xs :: [Int]+ , (id _:_) ++ [] :: [Int]+ , (id _:_) ++ (_:_) :: [Int]+ , tail _ ++ xs :: [Int]+ , tail _ ++ [] :: [Int]+ , tail _ ++ (_:_) :: [Int]+ , (_ ++ _) ++ xs :: [Int]+ , (_ ++ _) ++ [] :: [Int]+ , (_ ++ _) ++ (_:_) :: [Int]+ , zs ++ _ :: [Int]+ , [0,0] ++ _ :: [Int]+ , [1] ++ _ :: [Int]+ , (_:ys) ++ _ :: [Int]+ , [_,0] ++ _ :: [Int]+ , (_:_:xs) ++ _ :: [Int]+ , [_,_] ++ _ :: [Int]+ , (_:_:_:_) ++ _ :: [Int]+ , (_:x:_) ++ _ :: [Int]+ , (_:0:_) ++ _ :: [Int]+ , (_:id _:_) ++ _ :: [Int]+ , (_:tail _) ++ _ :: [Int]+ , (_:(_ ++ _)) ++ _ :: [Int]+ , (x:xs) ++ _ :: [Int]+ , [x] ++ _ :: [Int]+ , (x:_:_) ++ _ :: [Int]+ , (0:xs) ++ _ :: [Int]+ , [0] ++ _ :: [Int]+ , (0:_:_) ++ _ :: [Int]+ , (id _:xs) ++ _ :: [Int]+ , [id _] ++ _ :: [Int]+ , (id _:_:_) ++ _ :: [Int]+ , (y:_) ++ _ :: [Int]+ , (1:_) ++ _ :: [Int]+ , (id x:_) ++ _ :: [Int]+ , (id 0:_) ++ _ :: [Int]+ , (id (id _):_) ++ _ :: [Int]+ , (negate _:_) ++ _ :: [Int]+ , (abs _:_) ++ _ :: [Int]+ , (_ + _:_) ++ _ :: [Int]+ , (head _:_) ++ _ :: [Int]+ , (ord _:_) ++ _ :: [Int]+ , tail xs ++ _ :: [Int]+ , tail [] ++ _ :: [Int]+ , tail (_:_) ++ _ :: [Int]+ , (_ ++ xs) ++ _ :: [Int]+ , (_ ++ []) ++ _ :: [Int]+ , (_ ++ (_:_)) ++ _ :: [Int]+ , (xs ++ _) ++ _ :: [Int]+ , ([] ++ _) ++ _ :: [Int]+ , ((_:_) ++ _) ++ _ :: [Int]+ , sort _ ++ _ :: [Int]+ , insert _ _ ++ _ :: [Int]+ , sort ys :: [Int]+ , sort [0] :: [Int]+ , sort (_:xs) :: [Int]+ , sort [_] :: [Int]+ , sort (_:_:_) :: [Int]+ , sort (x:_) :: [Int]+ , sort (0:_) :: [Int]+ , sort (id _:_) :: [Int]+ , sort (tail _) :: [Int]+ , sort (_ ++ _) :: [Int]+ , insert _ ys :: [Int]+ , insert _ [0] :: [Int]+ , insert _ (_:xs) :: [Int]+ , insert _ [_] :: [Int]+ , insert _ (_:_:_) :: [Int]+ , insert _ (x:_) :: [Int]+ , insert _ (0:_) :: [Int]+ , insert _ (id _:_) :: [Int]+ , insert _ (tail _) :: [Int]+ , insert _ (_ ++ _) :: [Int]+ , insert x xs :: [Int]+ , insert x [] :: [Int]+ , insert x (_:_) :: [Int]+ , insert 0 xs :: [Int]+ , insert 0 [] :: [Int]+ , insert 0 (_:_) :: [Int]+ , insert (id _) xs :: [Int]+ , insert (id _) [] :: [Int]+ , insert (id _) (_:_) :: [Int]+ , insert y _ :: [Int]+ , insert 1 _ :: [Int]+ , insert (id x) _ :: [Int]+ , insert (id 0) _ :: [Int]+ , insert (id (id _)) _ :: [Int]+ , insert (negate _) _ :: [Int]+ , insert (abs _) _ :: [Int]+ , insert (_ + _) _ :: [Int]+ , insert (head _) _ :: [Int]+ , insert (ord _) _ :: [Int]+ , (z +) :: Int -> Int+ , ((-1) +) :: Int -> Int+ , (id y +) :: Int -> Int+ , (id 1 +) :: Int -> Int+ , (id (id x) +) :: Int -> Int+ , (id (id 0) +) :: Int -> Int+ , (id (id (id _)) +) :: Int -> Int+ , (id (negate _) +) :: Int -> Int+ , (id (abs _) +) :: Int -> Int+ , (id (_ + _) +) :: Int -> Int+ , (id (head _) +) :: Int -> Int+ , (id (ord _) +) :: Int -> Int+ , (negate x +) :: Int -> Int+ , (negate 0 +) :: Int -> Int+ , (negate (id _) +) :: Int -> Int+ , (abs x +) :: Int -> Int+ , (abs 0 +) :: Int -> Int+ , (abs (id _) +) :: Int -> Int+ , ((_ + x) +) :: Int -> Int+ , ((_ + 0) +) :: Int -> Int+ , ((_ + id _) +) :: Int -> Int+ , ((x + _) +) :: Int -> Int+ , ((0 + _) +) :: Int -> Int+ , ((id _ + _) +) :: Int -> Int+ , (_ * _ +) :: Int -> Int+ , (f _ +) :: Int -> Int+ , (head xs +) :: Int -> Int+ , (head [] +) :: Int -> Int+ , (head (_:_) +) :: Int -> Int+ , (ord c +) :: Int -> Int+ , (ord 'a' +) :: Int -> Int+ , (y *) :: Int -> Int+ , (1 *) :: Int -> Int+ , (id x *) :: Int -> Int+ , (id 0 *) :: Int -> Int+ , (id (id _) *) :: Int -> Int+ , (negate _ *) :: Int -> Int+ , (abs _ *) :: Int -> Int+ , ((_ + _) *) :: Int -> Int+ , (head _ *) :: Int -> Int+ , (ord _ *) :: Int -> Int+ , h :: Int -> Int+ , (q ||) :: Bool -> Bool+ , (not p ||) :: Bool -> Bool+ , (not False ||) :: Bool -> Bool+ , (not True ||) :: Bool -> Bool+ , (not (not _) ||) :: Bool -> Bool+ , ((_ || _) ||) :: Bool -> Bool+ , (p &&) :: Bool -> Bool+ , (False &&) :: Bool -> Bool+ , (True &&) :: Bool -> Bool+ , (not _ &&) :: Bool -> Bool+ , (_ ==>) :: Bool -> Bool+ ]+ , ...+ ]
+ test/model/eg/u-extrapolate.out view
@@ -0,0 +1,21 @@+sort . sort = sort++++ Tests passed.++length . nub = length (incorrect when there are repeated elements)+*** Falsified, counterexample: [0,0] :: [Int]+ generalization: x:x:xs :: [Int]++\(x,y) -> x + y == y + x++++ Tests passed.++\x -> x == x + 1 (always incorrect)+*** Falsified, counterexample: 0 :: Int+ generalization: x :: Int++\(x,y) -> x + y == x + x (incorrect)+*** Falsified, counterexample: (0,1) :: (Int,Int)++\(x,y) -> x /= y (incorrect whenever x and y are equal)+*** Falsified, counterexample: (0,0) :: (Int,Int)+ generalization: (x,x) :: (Int,Int)+
+ test/model/eg/u-speculate.out view
@@ -0,0 +1,45 @@+Equations about _, 0, (+), abs:+abs 0 = 0+x + 0 = x+0 + x = x+abs (abs x) = abs x+x + y = y + x+abs (x + y) = abs (y + x)+abs (x + abs x) = x + abs x+abs (abs x + x) = x + abs x+abs x + abs x = abs (x + x)+x + (y + z) = x + (z + y)+x + (y + z) = y + (x + z)+x + (y + z) = y + (z + x)+x + (y + z) = z + (x + y)+x + (y + z) = z + (y + x)+(x + y) + z = x + (y + z)+(x + y) + z = x + (z + y)+(x + y) + z = y + (x + z)+(x + y) + z = y + (z + x)+(x + y) + z = z + (y + x)+(x + y) + z = (x + z) + y+(x + y) + z = (y + x) + z+(x + y) + z = (y + z) + x+(x + y) + z = (z + x) + y+(x + y) + z = (z + y) + x++Equations about _, False, True, not:+not False = True+not True = False+not (not p) = p++Equations about _, _, [], (:), (++), sort:+sort [] = []+xs ++ [] = xs+[] ++ xs = xs+sort (sort xs) = sort xs+sort [x] = [x]+[x] ++ xs = x:xs+sort (xs ++ ys) = sort (ys ++ xs)+sort (x:sort xs) = sort (x:xs)+sort (xs ++ sort ys) = sort (xs ++ ys)+sort (sort xs ++ ys) = sort (xs ++ ys)+(x:xs) ++ ys = x:(xs ++ ys)+(xs ++ ys) ++ zs = xs ++ (ys ++ zs)+
+ test/name-derive.hs view
@@ -0,0 +1,56 @@+-- Copyright (c) 2019 Rudy Matela.+-- Distributed under the 3-Clause BSD licence (see the file LICENSE).+{-# LANGUAGE TemplateHaskell #-}++import Test++import Data.Express.Utils.List++data Peano = Zero | Succ Peano deriving Show+data List a = a :- List a | Nil deriving Show+data Bush a = Bush a :-: Bush a | Leaf a deriving (Show, Eq)+data Tree a = Node (Tree a) a (Tree a) | Null deriving (Show, Eq)+deriveName ''Peano+deriveName ''List+deriveName ''Bush+deriveName ''Tree++-- Recursive nested datatype cascade+data RN = RN RN0 (RN1 Int) (RN2 Int RN)+data RN0 = Nest0 Int | Recurse0 RN+data RN1 a = Nest1 a | Recurse1 RN+data RN2 a b = Nest2 a b | Recurse2 RN+deriveNameCascading ''RN++-- Those should have no effect (instance already exists):+{- uncommenting those should generate warnings+deriveName ''Bool+deriveName ''Maybe+deriveName ''Either+-}++-- Those should not generate warnings+deriveNameIfNeeded ''Bool+deriveNameIfNeeded ''Maybe+deriveNameIfNeeded ''Either++main :: IO ()+main = mainTest tests 5040++tests :: Int -> [Bool]+tests n =+ [ True++ , name (undefined :: Peano) == "p"+ , name (undefined :: List Int) == "l"+ , name (undefined :: Bush Int) == "b"+ , name (undefined :: Tree Int) == "t"+ , name (undefined :: List Bool) == "l"+ , name (undefined :: Bush Bool) == "b"+ , name (undefined :: Tree Bool) == "t"++ , name (undefined :: RN) == "r"+ , name (undefined :: RN0) == "r"+ , name (undefined :: RN1 Int) == "r"+ , name (undefined :: RN2 Bool Int) == "r"+ ]
+ test/name.hs view
@@ -0,0 +1,64 @@+-- Copyright (c) 2017-2018 Rudy Matela. -- Distributed under the 3-Clause BSD licence (see the file LICENSE).+import Test++import Data.Express.Utils.List++main :: IO ()+main = mainTest tests 5040++tests :: Int -> [Bool]+tests n =+ [ True++ -- simple types+ , name (undefined :: Int) == "x"+ , name (undefined :: Integer) == "x"+ , name (undefined :: Char) == "c"+ , name (undefined :: Bool) == "p"+ , name (undefined :: Int -> Int) == "f"+ , name (undefined :: Double) == "x"++ -- lists+ , name (undefined :: [Int]) == "xs"+ , name (undefined :: [[Int]]) == "xss"+ , name (undefined :: [Bool]) == "ps"+ , name (undefined :: [[Bool]]) == "pss"++ -- eithers+ , name (undefined :: Either Bool Bool) == "epq"+ , name (undefined :: Either Int Int) == "exy"+ , name (undefined :: Either Bool Char) == "epc"++ -- maybes+ , name (undefined :: Maybe Int) == "mx"+ , name (undefined :: Maybe [Int]) == "mxs"+ , name (undefined :: Maybe [[Int]]) == "mxss"++ -- pairs+ , name (undefined :: (Int,Int)) == "xy"+ , name (undefined :: (Bool,Bool)) == "pq"+ , name (undefined :: (Char,Char)) == "cd"+ , name (undefined :: (Bool,Int)) == "px"+ , name (undefined :: (Int,Bool)) == "xp"++ -- triples+ , name (undefined :: (Int,Int,Int)) == "xyz"+ , name (undefined :: (Bool,Bool,Bool)) == "pqr"+ , name (undefined :: (Char,Char,Char)) == "cde"+ , name (undefined :: (Int,Bool,Char)) == "xpc"++ -- tuples+ , name (undefined :: (Int,Int,Int,Int)) == "xxxx"+ , name (undefined :: (Int,Int,Int,Int,Int)) == "xxxxx"+ , name (undefined :: (Int,Int,Int,Int,Int,Int)) == "xxxxxx"+ , name (undefined :: (Int,Int,Int,Int,Int,Int,Int)) == "xxxxxxx"+ , name (undefined :: (Int,Int,Int,Int,Int,Int,Int,Int)) == "xxxxxxxx"+ , name (undefined :: (Int,Int,Int,Int,Int,Int,Int,Int,Int)) == "xxxxxxxxx"+ , name (undefined :: (Int,Int,Int,Int,Int,Int,Int,Int,Int,Int)) == "xxxxxxxxxx"+ , name (undefined :: (Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int)) == "xxxxxxxxxxx"+ , name (undefined :: (Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int)) == "xxxxxxxxxxxx"++ , name (undefined :: (Bool,Bool,Bool,Bool)) == "pppp"+ , name (undefined :: (Bool,Bool,Bool,Bool,Bool)) == "ppppp"+ , name (undefined :: (Bool,Bool,Bool,Bool,Bool,Bool)) == "pppppp"+ ]
+ test/ord.hs view
@@ -0,0 +1,46 @@+-- Copyright (c) 2019 Rudy Matela. -- Distributed under the 3-Clause BSD licence (see the file LICENSE).+import Test++main :: IO ()+main = mainTest tests 5040++tests :: Int -> [Bool]+tests n =+ [ True++ , holds n $ (okEqOrd :: Expr -> Expr -> Expr -> Bool)+ , holds n $ \(Ill e0) (Ill e1) (Ill e2) -> okEqOrd e0 e1 e2++ -- Holes < Values < Apps+ , xx < zero+ , zero < zero -+- one+ , xx < xx -+- yy+ , zero < xx -+- yy++ -- Less arity is less+ , zero < absE+ , absE < times+ , ae < ordE+ , ordE < times+ , value "id" (id -:> int) < value "id" (id -:> [int])+ , value "id" (id -:> [int]) < value "id" (id -:> [[int]])+ , value "id" (id -:> int) < value "sum" (sum -:> [int])+ , value "id" (id -:> int) < value "(:[])" ((:[]) -:> int)++ -- precedent types+ , pp < xx+ , cc < xx+ , pp < cc+ , xx < xxs+ , ae < zero+ , true < zero+ , true < ae+ , zero < nil++ -- other precedence rules+ , (xx -+- xx) < (xx -+- (xx -+- xx))+ , ((xx -+- xx) -+- xx) > (xx -+- (xx -+- xx))+ , xx < yy+ , zero < one+ , xx < zero+ ]
+ test/sdist view
@@ -0,0 +1,33 @@+#!/bin/bash+#+# test/sdist: tests the package generated by "cabal sdist".+#+# Copyright (c) 2015-2018 Rudy Matela.+# Distributed under the 3-Clause BSD licence.+export LC_ALL=C # consistent sort+pkgver=` cat *.cabal | grep "^version:" | sed -e "s/version: *//"`+pkgname=`cat *.cabal | grep "^name:" | sed -e "s/name: *//"`+pkg=$pkgname-$pkgver+set -x+cabal sdist &&+cd dist &&+tar -tf $pkg.tar.gz | sort --ignore-case > ls-cabal-i &&+tar -tf $pkg.tar.gz | sort --ignore-case --unique > ls-cabal-iu &&+diff -rud ls-cabal-i ls-cabal-iu &&+rm -f ls-cabal ls-cabal-ignore-case &&+if [ -d ../.git ]+then+ # on git repo, test if files are the same+ git -C .. ls-files | sort > ls-git &&+ tar -tf $pkg.tar.gz | grep -v "/$" | sed -e "s,$pkg/,," | sort > ls-cabal &&+ diff -rud ls-git ls-cabal &&+ rm -f ls-git ls-cabal+else+ # outside of git repo, test build+ rm -rf $pkg/ &&+ tar -xzf $pkg.tar.gz &&+ cd $pkg/ &&+ cabal configure --enable-tests --enable-benchmarks &&+ cabal build &&+ cabal test+fi
+ test/show.hs view
@@ -0,0 +1,82 @@+-- Copyright (c) 2017-2018 Rudy Matela. -- Distributed under the 3-Clause BSD licence (see the file LICENSE).+import Test++import Data.Express.Utils.List++main :: IO ()+main = mainTest tests 5040++tests :: Int -> [Bool]+tests n =+ [ True++ -- showing expressions++ , show zero == "0 :: Int"+ , show two == "2 :: Int"+ , show minusOne == "-1 :: Int"+ , show (one -+- two -*- three) == "1 + 2 * 3 :: Int"+ , show ((one -+- two) -*- three) == "(1 + 2) * 3 :: Int"++ , show plus == "(+) :: Int -> Int -> Int"+ , show times == "(*) :: Int -> Int -> Int"++ , show (plus :$ one) == "(1 +) :: Int -> Int"+ , show (times :$ (minusOne -+- two)) == "(((-1) + 2) *) :: Int -> Int"++ , show ffE == "f :: Int -> Int"+ , show (ff xx) == "f x :: Int"+ , show (var "f" (undefined :: Int -> Int -> Int)) == "f :: Int -> Int -> Int"+ , show (var "f" (undefined :: Int -> Int -> Int) :$ one) == "f 1 :: Int -> Int"+ , show (var "f" (undefined :: Int -> Int -> Int) :$ one :$ two) == "f 1 2 :: Int"+ , show (var "`f`" (undefined :: Int -> Int -> Int) :$ one) == "(1 `f`) :: Int -> Int"+ , show (var "`f`" (undefined :: Int -> Int -> Int) :$ one :$ two) == "1 `f` 2 :: Int"+ , show (one -?- two) == "1 ? 2 :: Int"+ , show (value "`compare`" (compare :: Int->Int->Ordering) :$ one) == "(1 `compare`) :: Int -> Ordering"+ , show (value "`compare`" (compare :: Int->Int->Ordering) :$ one :$ two) == "1 `compare` 2 :: Ordering"++ , holds n $ show . mapVars (\(Value ('_':s) d) -> Value (if null s then "_" else s) d) === show+--, holds n $ show . mapConsts (\(Value s d) -> Value ('_':s) d) === show -- TODO:++ , show emptyString == "\"\" :: [Char]"+ , show (space -:- emptyString) == "\" \" :: [Char]"+ , show (space -:- ccs) == "' ':cs :: [Char]"+ , show (ae -:- bee -:- emptyString) == "\"ab\" :: [Char]"+ , show (ae -:- bee -:- ccs) == "'a':'b':cs :: [Char]"+ , show (ae -:- space -:- bee -:- lineBreak -:- emptyString) == "\"a b\\n\" :: [Char]"+ , show (cc -:- space -:- dd -:- lineBreak -:- emptyString) == "c:' ':d:\"\\n\" :: [Char]"+ , show (cc -:- space -:- dd -:- lineBreak -:- ccs) == "c:' ':d:'\\n':cs :: [Char]"+ , show (cc -:- ae -:- bee -:- emptyString) == "c:\"ab\" :: [Char]"+ , show (cc -:- ae -:- bee -:- space -:- ae -:- bee -:- emptyString) == "c:\"ab ab\" :: [Char]"++ , show one == "1 :: Int"+ , show (minusOne) == "-1 :: Int"+ , show (one -+- one) == "1 + 1 :: Int"+ , show (minusOne -+- minusOne) == "(-1) + (-1) :: Int"++ , show (zero -|- one) == "(0,1) :: (Int,Int)"+ , show (minusOne -|- minusOne) == "(-1,-1) :: (Int,Int)"+ , show (triple zero one two) == "(0,1,2) :: (Int,Int,Int)"+ , show (quadruple minusOne zero one two) == "(-1,0,1,2) :: (Int,Int,Int,Int)"+ , show (quintuple minusOne zero one two three) == "(-1,0,1,2,3) :: (Int,Int,Int,Int,Int)"+ , show (sixtuple minusTwo minusOne zero one two three) == "(-2,-1,0,1,2,3) :: (Int,Int,Int,Int,Int,Int)"++ , show (one -:- nil) == "[1] :: [Int]"+ , show (zero -:- one -:- nil) == "[0,1] :: [Int]"+ , show (minusOne -:- nil) == "[-1] :: [Int]"+ , show (minusOne -:- minusTwo -:- nil) == "[-1,-2] :: [Int]"+ , show (xx -:- minusTwo -:- yy -:- nil) == "[x,-2,y] :: [Int]"+ , show (xx -:- minusTwo -:- yy -:- xxs) == "x:(-2):y:xs :: [Int]"++ , show (ffE -$- zero) == "f $ 0 :: Int"+ , show (ggE -$- xx) == "g $ x :: Int"+ , show (ffE -$- minusOne) == "f $ (-1) :: Int"++ , holds n $ \e -> showExpr e `isPrefixOf` show e++ -- showing holes --+ , show (hole (undefined :: Int -> Int) :$ one) == "_ 1 :: Int"+ , show (hole (undefined :: Int -> Int) :$ xx) == "_ x :: Int"+ , show (hole (undefined :: Int -> Int -> Int) :$ one :$ xx) == "_ 1 x :: Int"+ , show (hole (undefined :: Int -> Int -> Int) :$ i_ :$ i_) == "_ _ _ :: Int"+ ]
+ test/utils.hs view
@@ -0,0 +1,53 @@+-- Copyright (c) 2017-2018 Rudy Matela. -- Distributed under the 3-Clause BSD licence (see the file LICENSE).+import Test++import Data.Express.Utils.List+import Data.Express.Utils.String+import Data.Express.Utils.Typeable++main :: IO ()+main = mainTest tests 5040++tests :: Int -> [Bool]+tests n =+ [ True++ , holds n $ \xs -> nubSort xs == nub (sort xs :: [Int])+ , holds n $ \xs -> nubSort xs == sort (nub xs :: [Int])++ , holds n $ isSubsetOf ==== (\xs ys -> all (`elem` ys) (xs :: [Int]))++ , elementTy (typeOf [True]) == boolTy+ , elementTy (elementTy (typeOf [[False]])) == boolTy+ , show (mkComparisonTy boolTy) == "Bool -> Bool -> Bool"+ , show (mkComparisonTy intTy) == "Int -> Int -> Bool"+ , show (mkCompareTy boolTy) == "Bool -> Bool -> Ordering"+ , show (mkCompareTy intTy) == "Int -> Int -> Ordering"++ , primeCycle [] == []+ , ["x", "y", "z", "x'", "y'", "z'", "x''"] `isPrefixOf` primeCycle ["x","y","z"]+ , ["x","x'","x''","x'''","x''''","x'''''"] `isPrefixOf` primeCycle ["x"]+ , ["i", "j", "k", "i'", "j'", "k'", "i''"] `isPrefixOf` primeCycle ["i","j","k"]+ , ["xy", "zw", "xy'", "zw'", "xy''"] `isPrefixOf` primeCycle ["xy","zw"]++ , ["x","y","z","x'","y'"] `isPrefixOf` variableNamesFromTemplate "x"+ , ["xs","ys","zs","xs'"] `isPrefixOf` variableNamesFromTemplate "xs"+ , ["xss","yss","zss","xss'"] `isPrefixOf` variableNamesFromTemplate "xss"+ , ["c","d","e","c'","d'"] `isPrefixOf` variableNamesFromTemplate "c"+ , ["s","t","u","s'","t'"] `isPrefixOf` variableNamesFromTemplate "s"+ , ["0","1","2","3","4"] `isPrefixOf` variableNamesFromTemplate "0"+ , ["1","2","3","4","5"] `isPrefixOf` variableNamesFromTemplate "1"+ , ["z","z1","z2","z3","z4"] `isPrefixOf` variableNamesFromTemplate "z"+ , ["y","y1","y2","y3","y4"] `isPrefixOf` variableNamesFromTemplate "y"+ , ["x1","x2","x3","x4"] `isPrefixOf` variableNamesFromTemplate "x1"+ , ["a0","a1","a2","a3"] `isPrefixOf` variableNamesFromTemplate "a0"+ , ["e1","e2","e3","e4"] `isPrefixOf` variableNamesFromTemplate "e1"+ , ["xs1","xs2","xs3"] `isPrefixOf` variableNamesFromTemplate "xs1"+ , ["xy","zw","xy'","zw'"] `isPrefixOf` variableNamesFromTemplate "xy"+ , ["ab","cd","ab'","cd'"] `isPrefixOf` variableNamesFromTemplate "ab"+ , ["xys","zws","xys'"] `isPrefixOf` variableNamesFromTemplate "xys"+ , ["xyz","uvw","xyz'","uvw'"] `isPrefixOf` variableNamesFromTemplate "xyz"+ , ["thing1", "thing2", "thing3"] `isPrefixOf` variableNamesFromTemplate "thing1"+ , ["thingAndThing", "thingAndThing'", "thingAndThing''", "thingAndThing'''"]+ `isPrefixOf` variableNamesFromTemplate "thingAndThing"+ ]