packages feed

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 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"+  ]