ChasingBottoms (empty) → 1.2.2
raw patch · 63 files changed
+12544/−0 lines, 63 filesdep +QuickCheckdep +basedep +containersbuild-type:Customsetup-changedbinary-added
Dependencies added: QuickCheck, base, containers, mtl, random
Files
- ChasingBottoms.cabal +46/−0
- Header +96/−0
- LICENCE +23/−0
- Makefile +73/−0
- README +28/−0
- Setup.hs +3/−0
- Test/ChasingBottoms.hs +40/−0
- Test/ChasingBottoms/Approx.hs +106/−0
- Test/ChasingBottoms/Approx/Tests.hs +200/−0
- Test/ChasingBottoms/ApproxShow.hs +138/−0
- Test/ChasingBottoms/ApproxShow/Tests.hs +52/−0
- Test/ChasingBottoms/ContinuousFunctions.hs +463/−0
- Test/ChasingBottoms/ContinuousFunctions/Tests.hs +219/−0
- Test/ChasingBottoms/IsBottom.hs +103/−0
- Test/ChasingBottoms/IsBottom/Tests.hs +79/−0
- Test/ChasingBottoms/IsType.hs +41/−0
- Test/ChasingBottoms/IsType/Tests.hs +26/−0
- Test/ChasingBottoms/Nat.hs +109/−0
- Test/ChasingBottoms/Nat/Tests.hs +239/−0
- Test/ChasingBottoms/SemanticOrd.hs +253/−0
- Test/ChasingBottoms/SemanticOrd/Tests.hs +118/−0
- Test/ChasingBottoms/TestLibraryWhenCompiling.hs +21/−0
- Test/ChasingBottoms/TestUtilities.hs +433/−0
- Test/ChasingBottoms/TestUtilities/Generators.hs +386/−0
- Test/ChasingBottoms/Tests.hs +75/−0
- Test/ChasingBottoms/TimeOut.hs +130/−0
- Test/ChasingBottoms/TimeOut/Tests.hs +31/−0
- docs/Test-ChasingBottoms-Approx.html +339/−0
- docs/Test-ChasingBottoms-ApproxShow.html +369/−0
- docs/Test-ChasingBottoms-ContinuousFunctions.html +1390/−0
- docs/Test-ChasingBottoms-IsBottom.html +380/−0
- docs/Test-ChasingBottoms-Nat.html +484/−0
- docs/Test-ChasingBottoms-SemanticOrd.html +940/−0
- docs/Test-ChasingBottoms-TimeOut.html +612/−0
- docs/Test-ChasingBottoms.html +187/−0
- docs/doc-index-47.html +154/−0
- docs/doc-index-60.html +154/−0
- docs/doc-index-61.html +146/−0
- docs/doc-index-62.html +154/−0
- docs/doc-index-92.html +146/−0
- docs/doc-index-A.html +218/−0
- docs/doc-index-B.html +146/−0
- docs/doc-index-C.html +146/−0
- docs/doc-index-E.html +154/−0
- docs/doc-index-F.html +194/−0
- docs/doc-index-G.html +146/−0
- docs/doc-index-I.html +170/−0
- docs/doc-index-L.html +154/−0
- docs/doc-index-M.html +170/−0
- docs/doc-index-N.html +178/−0
- docs/doc-index-O.html +146/−0
- docs/doc-index-P.html +166/−0
- docs/doc-index-R.html +154/−0
- docs/doc-index-S.html +194/−0
- docs/doc-index-T.html +206/−0
- docs/doc-index-V.html +146/−0
- docs/doc-index.html +132/−0
- docs/haddock.css +235/−0
- docs/haddock.js +15/−0
- docs/haskell_icon.gif binary
- docs/index.html +488/−0
- docs/minus.gif binary
- docs/plus.gif binary
+ ChasingBottoms.cabal view
@@ -0,0 +1,46 @@+name: ChasingBottoms+version: 1.2.2+license: OtherLicense+license-file: LICENCE+copyright: Copyright (c) Nils Anders Danielsson 2004-2007.+author: Nils Anders Danielsson+maintainer: http://www.cs.chalmers.se/~nad/contact.html+stability: experimental+homepage: http://www.cs.chalmers.se/~nad/software/#Chasing Bottoms+package-url: http://www.cs.chalmers.se/~nad/software/ChasingBottoms/ChasingBottoms.tgz+synopsis: For testing partial and infinite values.+description: Do you ever feel the need to test code involving bottoms (e.g. calls+ to the error function), or code involving infinite values? Then this+ library could be useful for you.+category: Test+tested-with: GHC == 6.8.1+cabal-version: >= 1.2 && < 2++flag small_base+ description: Choose the new smaller, split-up base package.++library+ exposed-modules:+ Test.ChasingBottoms,+ Test.ChasingBottoms.Approx,+ Test.ChasingBottoms.ApproxShow,+ Test.ChasingBottoms.ContinuousFunctions,+ Test.ChasingBottoms.IsBottom,+ Test.ChasingBottoms.Nat,+ Test.ChasingBottoms.SemanticOrd,+ Test.ChasingBottoms.TimeOut++ other-modules: Test.ChasingBottoms.IsType++ build-depends: QuickCheck >= 1.1 && < 2,+ mtl >= 1.1 && < 2+ if flag(small_base)+ build-depends: base >= 3 && < 4,+ containers >= 0.1 && < 1,+ random >= 1 && < 2+ else+ build-depends: base >= 2 && < 3++-- It would be nice if the tests that can be accessed through+-- Test.ChasingBottoms.Tests.main could be run automatically using+-- Cabal (in a simple way). See make test.
+ Header view
@@ -0,0 +1,96 @@+Do you ever feel the need to test code involving bottoms (e.g. calls to+the @error@ function), or code involving infinite values? Then this+library could be useful for you.++It is usually easy to get a grip on bottoms by showing a value and+waiting to see how much gets printed before the first exception is+encountered. However, that quickly gets tiresome and is hard to automate+using e.g. QuickCheck+(<http://www.cs.chalmers.se/~rjmh/QuickCheck/>). With this library you+can do the tests as simply as the following examples show.++Testing explicitly for bottoms:++ [@> isBottom (head [\])@] @True@++ [@> isBottom bottom@] @True@++ [@> isBottom (\\_ -> bottom)@] @False@++ [@> isBottom (bottom, bottom)@] @False@++Comparing finite, partial values:++ [@> ((bottom, 3) :: (Bool, Int)) ==! (bottom, 2+5-4)@] @True@++ [@> ((bottom, bottom) :: (Bool, Int)) <! (bottom, 8)@] @True@++Showing partial and infinite values (@\\\/!@ is join and @\/\\!@ is meet):++ [@> approxShow 4 $ (True, bottom) \\\/! (bottom, \'b\')@] @\"Just (True, \'b\')\"@++ [@> approxShow 4 $ (True, bottom) \/\\! (bottom, \'b\')@] @\"(_|_, _|_)\"@++ [@> approxShow 4 $ ([1..\] :: [Int\])@] @\"[1, 2, 3, _\"@++ [@> approxShow 4 $ (cycle [bottom\] :: [Bool\])@] @\"[_|_, _|_, _|_, _\"@++Approximately comparing infinite, partial values:++ [@> approx 100 [2,4..\] ==! approx 100 (filter even [1..\] :: [Int\])@] @True@++ [@> approx 100 [2,4..\] \/=! approx 100 (filter even [bottom..\] :: [Int\])@] @True@++The code above relies on the fact that @bottom@, just as @error+\"...\"@, @undefined@ and pattern match failures, yield+exceptions. Sometimes we are dealing with properly non-terminating+computations, such as the following example, and then it can be nice to+be able to apply a time-out:++ [@> timeOut' 1 (reverse [1..5\]) >>= print@] @Value [5,4,3,2,1]@++ [@> timeOut' 1 (reverse [1..\]) >>= print@] @NonTermination@++The time-out functionality can be used to treat \"slow\" computations as+bottoms:++ [@> let tweak = Tweak { approxDepth = Just 5, timeOutLimit = Just 2 }@]++ [@> semanticEq tweak (reverse [1..\], [1..\]) (bottom :: [Int\], [1..\] :: [Int\])@] @True@++ [@> let tweak = noTweak { timeOutLimit = Just 2 }@]++ [@> semanticJoin tweak (reverse [1..\], True) ([\] :: [Int\], bottom)@] @Just ([],True)@++This can of course be dangerous:++ [@> let tweak = noTweak { timeOutLimit = Just 0 }@]++ [@> semanticEq tweak (reverse [1..100000000\]) (bottom :: [Integer\])@] @True@++Timeouts can also be applied to @IO@ computations:++ [@> let primes = unfoldr (\\(x:xs) -> Just (x, filter ((\/= 0) . (\`mod\` x)) xs)) [2..\]@]++ [@> timeOutMicro 100 (print $ filter ((== 1) . (\`mod\` 83)) primes) >>= print@] @[167,499NonTermination@++ [@> timeOutMicro 100 (print $ take 4 $ filter ((== 1) . (\`mod\` 83)) primes) >>= print@] @[167,499,997NonTermination@++ [@> timeOutMicro 100 (print $ take 4 $ filter ((== 1) . (\`mod\` 83)) primes) >>= print@] @[167,499,997,1163]@++ [@ @] @Value ()@++All the type annotations above are required.++For the underlying theory and a larger example involving use of+QuickCheck, see the article \"Chasing Bottoms, A Case Study in Program+Verification in the Presence of Partial and Infinite Values\"+(<http://www.cs.chalmers.se/~nad/publications/danielsson-jansson-mpc2004.html>).++The code has been tested under GHC 6.8. Most parts can probably be+ported to other Haskell compilers, but that would require some work.+The @TimeOut@ functions require preemptive scheduling, and most of the+rest requires @Data.Generics@; @isBottom@ only requires exceptions,+though.++Source code: <http://www.cs.chalmers.se/~nad/software/ChasingBottoms/ChasingBottoms.tar.gz>.
+ LICENCE view
@@ -0,0 +1,23 @@+I have chosen to distribute this library under the MIT/Expat licence:+---------------------------------------------------------------------++Copyright (c) 2004-2007 Nils Anders Danielsson++Permission is hereby granted, free of charge, to any person obtaining a+copy of this software and associated documentation files (the+"Software"), to deal in the Software without restriction, including+without limitation the rights to use, copy, modify, merge, publish,+distribute, sublicense, and/or sell copies of the Software, and to+permit persons to whom the Software is furnished to do so, subject to+the following conditions:++The above copyright notice and this permission notice shall be included+in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ Makefile view
@@ -0,0 +1,73 @@+# This Makefile is currently only used to build the documentation and+# to run a test suite automatically using darcs.++########################################################################+# You may need to edit the following variables:++# Path to Haddock.+HADDOCK ?= haddock++# URL prefix leading to Haddock documentation for the hierarchical+# libraries.+GHC_DOC_URL ?= http://www.haskell.org/ghc/docs/latest/html/libraries++# Path prefix leading to Haddock interface files for the hierarchical+# libraries. These files should be compiled using a Haddock program+# which is interface compatible with the one listed above (same+# version).+GHC_DOC_PATH ?= /chalmers/sw/unsup/ghc-6.8.1/share/doc/ghc/libraries++# Documentation is stored in this directory. Note that the directory+# is emptied first.+DOCDIR = docs++# Path to GHC 6.8, used to run the tests.+GHC_68 ?= _ghc_6.8.1++# GHC packages necessary for building and testing the library.+PACKAGES = base-3.0.0.0 containers-0.1.0.0 random-1.0.0.0 mtl-1.1.0.0 \+QuickCheck-1.1.0.0 array-0.1.0.0++########################################################################++EXPOSED_SOURCES = ChasingBottoms.hs ChasingBottoms/Approx.hs \+ChasingBottoms/ApproxShow.hs ChasingBottoms/ContinuousFunctions.hs \+ChasingBottoms/IsBottom.hs ChasingBottoms/Nat.hs \+ChasingBottoms/SemanticOrd.hs ChasingBottoms/TimeOut.hs++HIDDEN_SOURCES = ChasingBottoms/IsType.hs ChasingBottoms/Tests.hs \+ChasingBottoms/Approx/Tests.hs ChasingBottoms/ApproxShow/Tests.hs \+ChasingBottoms/ContinuousFunctions/Tests.hs \+ChasingBottoms/IsBottom/Tests.hs ChasingBottoms/IsType/Tests.hs \+ChasingBottoms/Nat/Tests.hs ChasingBottoms/SemanticOrd/Tests.hs \+ChasingBottoms/TimeOut/Tests.hs ChasingBottoms/TestUtilities.hs \+ChasingBottoms/TestUtilities/Generators.hs \+ChasingBottoms/TestLibraryWhenCompiling.hs++FILES_TO_BE_EXCLUDED = .boring++$(DOCDIR) : $(DOCDIR)/index.html+$(DOCDIR)/index.html : $(addprefix Test/,$(EXPOSED_SOURCES)) Header+ -rm -rf $(DOCDIR)+ mkdir -p $(DOCDIR)+ $(HADDOCK) -h --title="Chasing Bottoms" --prologue=Header -o$(DOCDIR) \+ $(foreach pkg,$(PACKAGES),\+ -i$(GHC_DOC_URL)/$(pkg),$(GHC_DOC_PATH)/$(pkg)/`echo $(pkg) | sed -r -e 's/-.*//'`.haddock) \+ $(filter Test/%,$^)++# Target used by darcs dist.+# After building the documentation we remove the generated files. We+# do not want them included in the tar ball generated by darcs.+# We also remove some other files.+dist: $(DOCDIR)+ -rm $(FILES_TO_BE_EXCLUDED)++# Runs all tests using GHC 6.8.+compile = $(1) -ignore-dot-ghci -no-recomp -hide-all-packages \+ $(foreach pkg,$(PACKAGES),-package $(pkg)) --make $(2)+testWithCompiler = $(call compile,$(1),Test.ChasingBottoms) && $(call \+compile,$(1),Test.ChasingBottoms.Tests -main-is \+Test.ChasingBottoms.Tests.main -o tests) && ./tests+.PHONY : test+test:+ $(call testWithCompiler,$(GHC_68))
+ README view
@@ -0,0 +1,28 @@+ChasingBottoms+--------------++Building+--------++To build: Use Cabal, or use ghc --make Test.ChasingBottoms. (If+Test.ChasingBottoms is already installed you may need to add something+like -ignore-package ChasingBottoms.)++Do not use Cabal to build the documentation. Use make docs instead.+You may need to edit the Makefile first.++To run through the test suite, execute Test.ChasingBottoms.Tests.main.++Possible future work+--------------------++* Making it easier to test equality etc. of functions. (This may be+ easier using the new version of Scrap your boilerplate, Scrap your+ boilerplate with class.)++* More custom generators for partial and infinite values.++Known bugs+----------++None.
+ Setup.hs view
@@ -0,0 +1,3 @@+import Distribution.Simple++main = defaultMain
+ Test/ChasingBottoms.hs view
@@ -0,0 +1,40 @@+-- |+-- Module : Test.ChasingBottoms+-- Copyright : (c) Nils Anders Danielsson 2004-2007+-- License : See the file LICENCE.+-- +-- Maintainer : http://www.cs.chalmers.se/~nad/+-- Stability : experimental+-- Portability : non-portable (GHC-specific)+--+-- This module just re-exports all the other modules.++module Test.ChasingBottoms+ ( module Test.ChasingBottoms.Approx+ , module Test.ChasingBottoms.ApproxShow+ , module Test.ChasingBottoms.ContinuousFunctions+ , module Test.ChasingBottoms.IsBottom+ , module Test.ChasingBottoms.Nat+ , module Test.ChasingBottoms.SemanticOrd+ , module Test.ChasingBottoms.TimeOut+ ) where++import Test.ChasingBottoms.Approx+import Test.ChasingBottoms.ApproxShow+import Test.ChasingBottoms.ContinuousFunctions+import Test.ChasingBottoms.IsBottom+import Test.ChasingBottoms.Nat+import Test.ChasingBottoms.SemanticOrd+import Test.ChasingBottoms.TimeOut++{-++-- If this module is imported the library refuses to be built whenever+-- the tests fail. Doing this adds a dependency on Template Haskell,+-- though, and the compilation takes considerably longer, plus some+-- (intended) warnings are emitted. Furthermore, if some test should+-- fail, then the emitted error message is rather unreadable.++import Test.ChasingBottoms.TestLibraryWhenCompiling++-}
+ Test/ChasingBottoms/Approx.hs view
@@ -0,0 +1,106 @@+{-# OPTIONS -fglasgow-exts -fallow-undecidable-instances #-}++-- |+-- Module : Test.ChasingBottoms.Approx+-- Copyright : (c) Nils Anders Danielsson 2004-2007+-- License : See the file LICENCE.+-- +-- Maintainer : http://www.cs.chalmers.se/~nad/+-- Stability : experimental+-- Portability : non-portable (GHC-specific)+--++module Test.ChasingBottoms.Approx+ ( Approx(..)+ ) where++import Test.ChasingBottoms.Nat+import Data.Generics+import qualified Data.List as List++{-|+'Approx' is a class for approximation functions as described+in The generic approximation lemma, Graham Hutton and Jeremy+Gibbons, Information Processing Letters, 79(4):197-201, Elsevier+Science, August 2001, <http://www.cs.nott.ac.uk/~gmh/bib.html>.++Instances are provided for all members of the 'Data' type class. Due+to the limitations of the "Data.Generics" approach to generic+programming, which is not really aimed at this kind of application,+the implementation is only guaranteed to perform correctly, with+respect to the paper (and modulo any bugs), on non-mutually-recursive+sum-of-products datatypes. In particular, nested and mutually+recursive types are not handled correctly with respect to the+paper. The specification below is correct, though (if we assume that+the 'Data' instances are well-behaved).++In practice the 'approxAll' function can probably be more useful than+'approx'. It traverses down /all/ subterms, and it should be possible+to prove a variant of the approximation lemma which 'approxAll'+satisfies.+-}++class Approx a where+ -- | @'approxAll' n x@ traverses @n@ levels down in @x@ and replaces all+ -- values at that level with bottoms.+ approxAll :: Nat -> a -> a++ -- | 'approx' works like 'approxAll', but the traversal and+ -- replacement is only performed at subterms of the same monomorphic+ -- type as the original term. For polynomial datatypes this is+ -- exactly what the version of @approx@ described in the paper above+ -- does.+ approx :: Nat -> a -> a++instance Data a => Approx a where+ approxAll = approxAllGen+ approx = approxGen++-- From The generic approximation lemma (Hutton, Gibbons):++-- Generic definition for arbitrary datatype \mu F:+-- approx (n+1) = in . F (approx n) . out++-- Approximation lemma (valid if F is locally continuous),+-- for x, y :: \mu F:+-- x = y <=> forall n in Nat corresponding to natural numbers.+-- approx n x = approx n y++approxGen :: Data a => Nat -> a -> a+approxGen n | n == 0 = error "approx 0 = _|_"+ | otherwise =+ \(x :: a) -> gmapT (mkT (approxGen (pred n) :: a -> a)) x++-- We use mkT to only recurse on the original type. This solution is+-- actually rather nice! But sadly it doesn't work for nested or+-- mutually recursive types...++-- Note that the function is defined in the \n -> \x -> style, not+-- \n x -> which would mean something subtly different.++------------------------------------------------------------------------++-- Recurses on everything...++approxAllGen :: Data a => Nat -> a -> a+approxAllGen n | n == 0 = error "approx 0 = _|_"+ | otherwise = \x -> gmapT (approxAllGen (pred n)) x++------------------------------------------------------------------------++-- Behaves exactly like approxGen. (?)++approxGen' :: Data a => Nat -> a -> a+approxGen' n+ | n == 0 = error "approx 0 = _|_"+ | otherwise = \x ->+ let d = dataTypeOf x+ n' = pred n+ fun childTerm = if dataTypeOf childTerm == d then+ approxGen' n' childTerm+ else+ childTerm+ in gmapT fun x++instance Eq DataType where+ d1 == d2 = dataTypeRep d1 == dataTypeRep d2
+ Test/ChasingBottoms/Approx/Tests.hs view
@@ -0,0 +1,200 @@+{-# OPTIONS -fglasgow-exts #-}++-- | Tests of the functions in "Test.ChasingBottoms.Approx".++module Test.ChasingBottoms.Approx.Tests (tests) where++-- Improve the testing here. (Use QuickCheck when there is some proper+-- infrastructure for testing bottoms and infinite stuff. Hmm... This+-- module is part of that infrastructure, so be careful.)++import Test.ChasingBottoms.Approx+import Test.ChasingBottoms.IsBottom+import Test.ChasingBottoms.SemanticOrd+import Test.ChasingBottoms.Nat+import Data.Generics++data Tree = Lf | Br Tree Tree deriving (Typeable, Data)++leftInfinite = Br leftInfinite Lf+twoLevels = Br (Br bottom bottom) Lf+threeLevels = Br (Br (Br bottom bottom) Lf) Lf++-- A nested type:+data PerfectTree t = PL t | PB (PerfectTree (t, t))+ deriving (Show, Typeable, Data)++pTree :: PerfectTree Int+pTree = PB (PB (PL ((1, 2), (3, 4))))++-- Full form of PerfectTree: PT A = Lift (A + PT (Lift (A x A))).+-- Define F G A = Lift (A + G (Lift (A x A))).++type F g a = Either a (g (a, a))++-- Assume that F is locally continuous. We have PT = mu F = F (mu F),+-- i.e. PT a = F PT a, with operations+-- in :: F PT a -> PT a+-- out :: PT a -> F PT a+-- map :: (forall a . G a -> G' a) -> F G a -> F G' a++in_PT :: F PerfectTree t -> PerfectTree t+in_PT x = case x of+ Left t -> PL t+ Right tt -> PB tt++out_PT :: PerfectTree t -> F PerfectTree t+out_PT x = case x of+ PL t -> Left t+ PB tt -> Right tt++-- Pattern type signature added just for clarity.+map_PT :: (forall t . g t -> g' t) -> F g t' -> F g' t'+map_PT f x = case x of+ Left t -> Left t+ Right (tt :: g (t, t)) -> Right (f tt)++-- Note that we get a boring map using this kind of functor for nested+-- types:+fullMap_PT :: (forall a . a -> a) -> PerfectTree a -> PerfectTree a+fullMap_PT f = in_PT . map_PT (fullMap_PT f) . out_PT++-- And now we can define approx for this type:++approx_PT :: Nat -> PerfectTree a -> PerfectTree a+approx_PT n | n == 0 = error "approx 0 == _|_"+ | otherwise = in_PT . map_PT (approx_PT (pred n)) . out_PT++-- Some types with several parameters.+data A a b = A0 a | A1 b deriving (Typeable, Data)+data C a b = C0 (C a b) | C1 a b deriving (Typeable, Data)++-- Mutually recursive types:+data G a = G1 a | G2 (H a) deriving (Typeable, Data)+data H a = H1 (G a) | H2 a deriving (Typeable, Data)++{-++GH a (r1, r2) = (Lift (a + r2), Lift (r1 + a))++G a = fst (mu (GH a))+H a = snd (mu (GH a))++--> is used for arrows in the product category:+(a1, a2) --> (b1, b2) = (a1 -> b1, a2 -> b2)++in :: GH a (mu (GH a)) --> mu (GH a)+out :: GH a (mu (GH a)) <-- mu (GH a)++map_GH :: (p1 --> p2) -> (GH a p1 --> GH a p2)++-}++-- The following is an approximation, since we don't have proper+-- products. However, if no one breaks the abstraction this won't be a+-- problem.++-- Sadly I cannot write "type GH a (r1, r2) = (Either a r2, Either r1 a)".+type GH a r1 r2 = (Either a r2, Either r1 a)+type M a = (G a, H a)+-- And "type (a1, a2) :--> (b1, b2) = (a1 -> b1, a2 -> b2)" doesn't+-- work either...+type ProdArr a1 a2 b1 b2 = (a1 -> b1, a2 -> b2)++-- in_GH :: GH a (M a) :--> M a+in_GH :: ProdArr (Either a (H a)) (Either (G a) a) (G a) (H a)+in_GH = (in_G, in_H)+ where+ in_G e = case e of+ Left a -> G1 a+ Right m -> G2 m+ in_H e = case e of+ Left m -> H1 m+ Right a -> H2 a++-- out_GH :: M a :--> GH a (M a)+out_GH :: ProdArr (G a) (H a) (Either a (H a)) (Either (G a) a)+out_GH = (out_G, out_H)+ where+ out_G m = case m of+ G1 a -> Left a+ G2 m -> Right m+ out_H m = case m of+ H1 m -> Left m+ H2 a -> Right a++-- map_GH :: ((a1, a2) :--> (b1, b2)) -> (GH a a1 a2 :--> GH a b1 b2)+map_GH :: ProdArr a1 a2 b1 b2 -> ProdArr (Either a a2) (Either a1 a)+ (Either a b2) (Either b1 a)+map_GH gh = (map_G, map_H)+ where+ (g, h) = gh+ map_G e = case e of+ Left a -> Left a+ Right a2 -> Right (h a2)+ map_H e = case e of+ Left a1 -> Left (g a1)+ Right a -> Right a++(.*.) :: ProdArr b1 b2 c1 c2 -> ProdArr a1 a2 b1 b2 -> ProdArr a1 a2 c1 c2+(g1, h1) .*. (g2, h2) = (g1 . g2, h1 . h2)++-- approx_GH :: Nat -> (M a :--> M a)+approx_GH :: Nat -> ProdArr (G a) (H a) (G a) (H a)+approx_GH n | n == 0 = error "approx 0 == _|_"+ | otherwise = in_GH .*. map_GH (approx_GH (pred n)) .*. out_GH++approx_G :: Nat -> G a -> G a+approx_G = fst . approx_GH++approx_H :: Nat -> H a -> H a+approx_H = snd . approx_GH++g1 = G2 (H1 (G2 (H2 'a')))+h1 = H1 (G2 (H1 (G1 'b')))++tests :: [Bool]+tests =+ -- approx 0 = bottom.+ [ approx 0 ==! (bottom :: Int -> Int)+ , approx 0 ==! (bottom :: Char -> Char)+ , approx 0 True ==! (bottom :: Bool)++ -- approx (Succ n) /= bottom.+ , approx 1 /=! (bottom :: Int -> Int)+ , approx 1 /=! (bottom :: Char -> Char)++ -- approx n descends n levels.+ , approx 3 "test" ==! "tes" ++ bottom+ , approx 3 "tes" ==! "tes" ++ bottom+ , approx 3 "te" ==! "te"+ , approx 3 "t" ==! "t"++ -- This also works for infinite and multiply branching+ -- structures.+ , approx 2 leftInfinite ==! twoLevels+ , approx 3 leftInfinite ==! threeLevels++ -- Multiple parameter data types shouldn't pose a problem.+ , approx 1 (A0 (A1 True) :: A (A Char Bool) Char) ==! A0 (A1 True)+ , approx 2 (C0 (C1 'a' True)) ==! C0 (C1 'a' True)+ , approx 1 (C0 (C1 'a' True)) ==! C0 bottom++ -- Multiple parameter data types shouldn't pose a problem for+ -- approxAll either.+ , approxAll 1 (A0 (A1 True) :: A (A Char Bool) Char) ==! A0 bottom+ , approxAll 1 (C0 (C1 'a' True)) ==! C0 bottom++ -- approxAll doesn't descend only on the original type...+ , approxAll 1 (Just (Just (Just True))) ==! (Just bottom)+ , approxAll 2 pTree ==! approx_PT 2 pTree+ , approxAll 2 g1 ==! approx_G 2 g1++ -- ...but approx does...+ , approx 1 (Just (Just (Just True))) ==! (Just (Just (Just True)))++ -- ...more or less:+ , approx 2 pTree /=! approx_PT 2 pTree+ , approx 2 g1 /=! approx_G 2 g1+ -- Note that a perfect implementation would have equalities here.+ ]
+ Test/ChasingBottoms/ApproxShow.hs view
@@ -0,0 +1,138 @@+{-# OPTIONS -fglasgow-exts -fallow-undecidable-instances #-}++-- |+-- Module : Test.ChasingBottoms.ApproxShow+-- Copyright : (c) Nils Anders Danielsson 2004-2007+-- License : See the file LICENCE.+-- +-- Maintainer : http://www.cs.chalmers.se/~nad/+-- Stability : experimental+-- Portability : non-portable (GHC-specific)+--+-- Functions for converting arbitrary (non-function, partial,+-- possibly infinite) values into strings.++module Test.ChasingBottoms.ApproxShow+ ( Prec+ , ApproxShow(..)+ ) where++import Data.Generics+import Test.ChasingBottoms.IsBottom+import Test.ChasingBottoms.Nat+import Test.ChasingBottoms.IsType+import qualified Data.List as List++-- | Precedence level.+type Prec = Int++class ApproxShow a where+ -- | The 'Data' instance of 'ApproxShow' makes sure that+ -- @'approxShowsPrec' n@ behaves (more or less) like the derived+ -- version of 'showsPrec', with the following differences:+ --+ -- * After @n@ levels of descent into a term the output is+ -- replaced by @\"_\"@.+ --+ -- * All detectable occurences of bottoms are replaced by @\"_|_\"@.+ --+ -- * Non-bottom functions are displayed as @\"\<function \/= _|_\>\"@.+ -- + approxShowsPrec :: Nat -> Prec -> a -> ShowS+ approxShows :: Nat -> a -> ShowS+ approxShow :: Nat -> a -> String++ approxShows n a = approxShowsPrec n 0 a+ approxShow n a = approxShowsPrec n 0 a ""++instance Data a => ApproxShow a where+ approxShowsPrec n p = gShowsPrec False n p++-- This is a gigantic hack (due to special treatment of lists and+-- strings). Now I realise how I should have written it:+-- A wrapper taking care of n == 0 and bottoms.+-- A generic case treating ordinary data types+-- Special cases (type specific extensions) for tuples, functions,+-- lists and strings.+-- I'm not sure if it's possible to have a type specific extension that+-- works for, for instance, all list types, though. I guess that it+-- would have to be monomorphic.+--+-- Anyway, I don't have time improving this right now. All tests go+-- through, so this should be fine.++gShowsPrec :: Data a => Bool -> Nat -> Prec -> a -> ShowS+gShowsPrec insideList n p (a :: a)+ | n == 0 = showString "_"+ | isBottom a = showString "_|_"+ | isFunction a = showString "<function /= _|_>"+ | isTuple a = showParen True $ drive $+ List.intersperse (showString ", ") $+ (continueR (:) [] minPrec a)+ | isString a && isAtom a = when' (not insideList) (showString "\"") $+ showString "\"" -- End of string.+ | isString a = when' (not insideList) (showString "\"") $+ gmapQr (.) id+ ( id -- Dummy.+ `mkQ`+ (\c -> if n == 1 then showString "_" else+ if isBottom c then showString "_|_"+ else showChar c)+ `extQ`+ (\(a :: String) -> if n == 1 then id else+ if isBottom a then showString "_|_"+ else gShowsPrec True (pred n) minPrec a+ )+ ) a+ | isList a && isAtom a = when' (not insideList) (showString "[") $+ showString "]" -- End of list.+ | isList a = when' (not insideList) (showString "[") $+ gmapQr (.) id+ ( gShowsPrec False (pred n) minPrec+ `extQ`+ (\(a :: a) ->+ if n == 1 then id+ else if isBottom a then showString "_|_"+ else (if not (isAtom a) then showString ", "+ else id) .+ gShowsPrec True (pred n) minPrec a+ )+ ) a+ | isInfix a = showParen (not (isAtom a) && p > appPrec) $+ -- We know that we have at least two args,+ -- because otherwise we would have a function.+ let (arg1:arg2:rest) =+ continueR (:) [] (succ appPrec) a+ in (showParen (not (null rest)) $+ arg1 .^. showCon a .^. arg2+ ) . drive rest+ | otherwise = showParen (not (isAtom a) && p > appPrec) $+ showCon a .+ continueL (.^.) nil (succ appPrec) a+ + where+ continueL f x p = gmapQl f x (gShowsPrec False (pred n) p)+ continueR f x p = gmapQr f x (gShowsPrec False (pred n) p)++drive = foldr (.) id+nil = showString ""+f .^. g = f . showChar ' ' . g+appPrec = 10+minPrec = 0+-- Some infix constructors seem to have parentheses around them in+-- their conString representations. Maybe something should be done about+-- that. See the Q test case, and compare with ordinary lists.+showCon a = showString $ showConstr' a+ where+ showConstr' a+ | dataTypeRep (dataTypeOf a) == dataTypeRep (dataTypeOf 'c') = + "'" ++ showConstr (toConstr a) ++ "'"+ | otherwise = showConstr $ toConstr a+isAtom a = glength a == 0+isPrimitive a = not $ isAlgType (dataTypeOf a)+isInfix a = if isPrimitive a then+ False+ else+ constrFixity (toConstr a) == Infix+wrap s = \s' -> s . s' . s+when' b s = if b then (s .) else (id .)
+ Test/ChasingBottoms/ApproxShow/Tests.hs view
@@ -0,0 +1,52 @@+{-# OPTIONS -fglasgow-exts #-}++-- | Tests of the functions in "Test.ChasingBottoms.ApproxShow".++module Test.ChasingBottoms.ApproxShow.Tests (tests) where++import Test.ChasingBottoms.ApproxShow+import Test.ChasingBottoms.IsBottom+import Data.Generics++data T = L | B T T deriving (Typeable, Data)++left = B left L++data Q a = Q a ::: a | Q deriving (Typeable, Data)++pr n x template = do+ let s = approxShow n x+ putStr $ show (s == template)+ putStr " |"+ putStr s+ putStrLn "|"++tst n x template = approxShow n x == template++tests :: [Bool]+tests =+ [ tst 4 left "B (B (B (B _ _) L) L) L"+ , tst 4 (bottom :: Bool) "_|_"+ , tst 4 not "<function /= _|_>"+ , tst 4 ('a','b') "('a', 'b')"+ , tst 1 ('a','b') "(_, _)"+ , tst 4 (Q ::: 'a' ::: 'b' ::: 'c') "((Q ::: 'a') ::: 'b') ::: 'c'"+ , tst 2 (Q ::: 'a' ::: 'b' ::: 'c') "(_ ::: _) ::: 'c'"+ , tst 4 "abc" "\"abc\""+ , tst 4 [True, False, False] "[True, False, False]"+ , tst 2 "abc" "\"a_"+ , tst 2 [True, False, False] "[True, _"+ , tst 1 "" "\"\""+ , tst 1 ([] :: [Bool]) "[]"+ , tst 0 "" "_"+ , tst 0 ([] :: [Bool]) "_"+ , tst 4 ('a' : bottom : bottom) "\"a_|__|_"+ , tst 4 ('a' : bottom : bottom : []) "\"a_|__|_\""+ , tst 4 [True, bottom] "[True, _|_]"+ , tst 4 (True : bottom : bottom) "[True, _|__|_"+ , tst 4 (bottom ::: bottom ::: 'b' ::: 'c') "((_|_ ::: _|_) ::: 'b') ::: 'c'"+ , tst 2 ('a' : bottom : bottom) "\"a_"+ , tst 2 [True, bottom] "[True, _"+ , tst 2 (True : bottom : bottom) "[True, _"+ , tst 2 (bottom ::: bottom ::: 'b' ::: 'c') "(_ ::: _) ::: 'c'"+ ]
+ Test/ChasingBottoms/ContinuousFunctions.hs view
@@ -0,0 +1,463 @@+{-# OPTIONS -fglasgow-exts #-}++-- TODO: Can we pattern match on functions?+-- What about functions of several arguments? Can we have interleaved+-- pattern matching? Do we need to use currying to achieve this? What+-- limitations does that lead to?+-- TODO: getMatches: What happens with infinite input? Hmm... We do want the+-- possibility of non-termination, right?+-- TODO: getMatches: Frequencies?+-- TODO: match: Document limitations. Can functions be handled?++-- |+-- Module : Test.ChasingBottoms.ContinuousFunctions+-- Copyright : (c) Nils Anders Danielsson 2005-2007+-- License : See the file LICENCE.+-- +-- Maintainer : http://www.cs.chalmers.se/~nad/+-- Stability : experimental+-- Portability : non-portable (GHC-specific)+--+-- Note: /This module is unfinished and experimental. However, I do+-- not think that I will ever finish it, so I have released it in its+-- current state. The documentation below may not be completely+-- correct. The source code lists some things which should be+-- addressed./+--+-- A framework for generating possibly non-strict, partial,+-- continuous functions.+-- +-- The functions generated using the standard QuickCheck 'Arbitrary'+-- instances are all strict. In the presence of partial and infinite+-- values testing using only strict functions leads to worse coverage+-- than if more general functions are used, though.+--+-- Using 'isBottom' it is relatively easy to generate possibly+-- non-strict functions that are, in general, not monotone. For+-- instance, using+--+-- > type Cogen a = forall b. a -> Gen b -> Gen b+-- > +-- > integer :: Gen Integer+-- > integer = frequency [ (1, return bottom), (10, arbitrary) ]+-- > +-- > coBool :: CoGen Bool+-- > coBool b | isBottom b = variant 0+-- > coBool False = variant 1+-- > coBool True = variant 2+-- > +-- > function :: Cogen a -> Gen b -> Gen (a -> b)+-- > function coGen gen = promote (\a -> coGen a gen)+--+-- we can generate possibly non-strict functions from 'Bool' to+-- 'Integer' using @function coBool integer@. There is a high+-- likelihood that the functions generated are not monotone, though.+-- The reason that we can get non-monotone functions in a language+-- like Haskell is that we are using the impure function 'isBottom'.+--+-- Sometimes using possibly non-monotone functions is good enough,+-- since that set of functions is a superset of the continuous+-- functions. However, say that we want to test that @x+-- 'Test.ChasingBottoms.SemanticOrd.<=!' y@ implies that @f x+-- 'Test.ChasingBottoms.SemanticOrd.<=!' f y@ for all functions @f@+-- (whenever the latter expression returns a total result). This+-- property is not valid in the presence of non-monotone functions.+--+-- By avoiding 'isBottom' and, unlike the standard 'coarbitrary'+-- functions, deferring some pattern matches, we can generate+-- continuous, possibly non-strict functions. There are two steps+-- involved in generating a continuous function using the framework+-- defined here.+--+-- (1) First the argument to the function is turned into a+-- 'PatternMatch'. A 'PatternMatch' wraps up the pattern match on+-- the top-level constructor of the argument, plus all further+-- pattern matches on the children of the argument. Just like when+-- 'coarbitrary' is used a pattern match is represented as a+-- generator transformer. The difference here is that there is not+-- just one transformation per input, but one transformation per+-- constructor in the input. 'PatternMatch'es can be constructed+-- generically using 'match'.+-- +-- (2) Then the result is generated, almost like for a normal+-- 'Arbitrary' instance. However, for each constructor generated a+-- subset of the transformations from step 1 are applied. This+-- transformation application is wrapped up in the function+-- 'transform'.+--+-- The net result of this is that some pattern matches are performed+-- later, or not at all, so functions can be lazy.+--+-- Here is an example illustrating typical use of this framework:+--+-- > data Tree a+-- > = Branch (Tree a) (Tree a)+-- > | Leaf a+-- > deriving (Show, Typeable, Data)+-- > +-- > finiteTreeOf :: MakeResult a -> MakeResult (Tree a)+-- > finiteTreeOf makeResult = sized' tree+-- > where+-- > tree size = transform $+-- > if size == 0 then+-- > baseCase+-- > else+-- > frequency' [ (1, baseCase)+-- > , (1, liftM2 Branch tree' tree')+-- > ]+-- > where+-- > tree' = tree (size `div` 2)+-- > +-- > baseCase =+-- > frequency' [ (1, return bottom)+-- > , (2, liftM Leaf makeResult)+-- > ]+--+-- Note the use of 'transform'. To use this function to generate+-- functions of type @Bool -> Tree Integer@ we can use+--+-- > forAll (functionTo (finiteTreeOf flat)) $+-- > \(f :: Bool -> Tree Integer) ->+-- > ...++module Test.ChasingBottoms.ContinuousFunctions+ ( -- * Basic framework+ function+ , functionTo+ , PatternMatch(..)+ , GenTransformer+ , MakePM+ , MakeResult+ , transform+ -- * Liftings of some QuickCheck functionality+ , lift'+ , arbitrary'+ , choose'+ , elements'+ , oneof'+ , frequency'+ , sized'+ , resize'+ -- * Generic @MakePM@+ , match+ -- * Some @MakeResult@s+ , flat+ , finiteListOf+ , infiniteListOf+ , listOf+ ) where++import Test.QuickCheck+import Data.Sequence as Seq+import Data.Foldable as Seq (foldr)+import Prelude as P hiding (concat)+import Test.ChasingBottoms.IsBottom+import Control.Monad+import Control.Monad.Reader+import Control.Arrow+import System.Random+import Data.Generics+import qualified Data.List as L++------------------------------------------------------------------------+-- Generation of functions++-- | Generator for continuous, not necessarily strict functions.+-- Functions are generated by first generating pattern matches, and+-- then generating a result.++function :: MakePM a -> MakeResult b -> Gen (a -> b)+function makePM makeResult =+ promote $ \a -> run makeResult (singleton $ makePM a)++-- | 'functionTo' specialises 'function':+--+-- @+-- 'functionTo' = 'function' 'match'+-- @++functionTo :: Data a => MakeResult b -> Gen (a -> b)+functionTo = function match++------------------------------------------------------------------------+-- Pattern matching++-- | 'PatternMatch' packages up the possible outcomes of a pattern+-- match in a style suitable for generating functions. A pattern match+-- is a generator ('Gen') transformer based on the top-level+-- constructor, and a sequence (see+-- <http://www.soi.city.ac.uk/~ross/software/html/Data.Sequence.html>) of+-- 'PatternMatch'es based on the children of that constructor.++data PatternMatch+ = PatternMatch { apply :: GenTransformer+ -- ^ A generator transformer, in the style of 'coarbitrary'.+ , more :: Seq PatternMatch+ -- ^ Further pattern matches made possible by this+ -- match.+ }++-- | The type of a generator transformer.++type GenTransformer = forall a. Gen a -> Gen a++-- | This newtype is (currently) necessary if we want to use+-- 'GenTransformer' as an argument to a type constructor.++newtype GenTransformer' = GenT GenTransformer++-- | The type of a 'PatternMatch' generator.++type MakePM a = a -> PatternMatch++------------------------------------------------------------------------+-- Generic MakePM++-- These functions provided inspiration for the generic one below.++matchFlat :: Arbitrary a => MakePM a+matchFlat a = PatternMatch { apply = coarbitrary a, more = empty }++data Tree a+ = Branch (Tree a) (Tree a)+ | Leaf a+ deriving (Show, Typeable, Data)++matchTree :: MakePM a -> MakePM (Tree a)+matchTree match t = PatternMatch { apply = toVariant t, more = moreT t }+ where+ toVariant (Branch {}) = variant 1+ toVariant (Leaf {}) = variant 0++ moreT (Branch l r) = fromList [matchTree match l, matchTree match r]+ moreT (Leaf x) = singleton (match x)++-- | Generic implementation of 'PatternMatch' construction.++match :: forall a. Data a => MakePM a+match x = PatternMatch+ { apply = toVariant x+ , more = more x+ }+ where+ -- seq added since toConstr is not strict enough for+ -- one-constructor data types. (Bug reported; should be fixed in the+ -- CVS repository.)+ toVariant :: forall a b. Data a => a -> Gen b -> Gen b+ toVariant x = x `seq` case constrRep (toConstr x) of+ AlgConstr n -> variant (n - 1) -- n >= 1.+ IntConstr i -> coarbitrary i+ FloatConstr d -> coarbitrary d+ StringConstr s -> nonBottomError "match: Encountered StringConstr."++ more :: forall a. Data a => a -> Seq PatternMatch+ more = gmapQr (<|) empty match++------------------------------------------------------------------------+-- MakeResult monad++-- | Monad for generating results given previously generated pattern+-- matches.+--+-- A @'MakeResult' a@ should be implemented almost as other generators for+-- the type @a@, with the difference that 'transform' should be+-- used wherever the resulting function should be allowed to pattern+-- match (typically for each constructor emitted). See example above.++-- Note that we do not want to export a 'MonadReader' instance, so we+-- cannot define one...++newtype MakeResult a+ = MR { unMR :: ReaderT PatternMatches Gen a }+ deriving (Functor, Monad)++type PatternMatches = Seq PatternMatch++-- | Lowering of a 'MakeResult'.++run :: MakeResult a -> PatternMatches -> Gen a+run mr pms = runReaderT (unMR mr) pms++-- | Lifting of a 'Gen'.++lift' :: Gen a -> MakeResult a+lift' gen = MR $ lift gen++-- | Returns the 'PatternMatches' in scope.++getPMs :: MakeResult PatternMatches+getPMs = MR ask++withPMs :: (PatternMatches -> Gen a) -> MakeResult a+withPMs f = do+ pms <- getPMs+ lift' $ f pms++-- | 'transform' makes sure that the pattern matches get to influence+-- the generated value. See 'MakeResult'.++transform :: MakeResult a -> MakeResult a+transform makeResult = withPMs $ \pms -> do+ (GenT trans, keep) <- getMatches pms+ trans (run makeResult keep)++-- | Extracts some pattern matches to trigger right away. These+-- triggered pattern matches may result in new pattern matches which+-- may in turn also be triggered, and so on.++getMatches :: Seq PatternMatch -> Gen (GenTransformer', Seq PatternMatch)+getMatches pms = do+ -- Throw away pattern matches with probability 0.1.+ (_, pms') <- partition 9 pms+ -- Use pattern matches with probability 0.33.+ (use, keep) <- partition 2 pms'+ let transform = compose $ fmap apply use+ further = concat $ fmap more use+ if Seq.null further then+ return (GenT transform, keep)+ else do+ (GenT transform', keep') <- getMatches further+ return (GenT (transform . transform'), keep >< keep')++------------------------------------------------------------------------+-- Sequence helpers++-- | Concatenates arguments.++concat :: Seq (Seq a) -> Seq a+concat = Seq.foldr (><) empty++-- | Composes arguments.++compose :: Seq (a -> a) -> a -> a+compose = Seq.foldr (.) id++-- | Partitions a 'Seq'. The first argument (a positive integer) is+-- the relative probability with which elements end up in the second+-- part compared to the first one.++partition :: Int -> Seq a -> Gen (Seq a, Seq a)+partition freq ss = case viewl ss of+ EmptyL -> return (empty, empty)+ x :< xs -> do+ (ys, zs) <- partition freq xs+ frequency [ (1, return (x <| ys, zs))+ , (freq, return (ys, x <| zs))+ ]++------------------------------------------------------------------------+-- Lifting of QuickCheck's Gen monad++-- | Lifting of 'arbitrary'.++arbitrary' :: Arbitrary a => MakeResult a+arbitrary' = lift' arbitrary++-- | Lifting of 'choose'.++choose' :: Random a => (a, a) -> MakeResult a+choose' = lift' . choose++-- | Lifting of 'elements'.++elements' :: [a] -> MakeResult a+elements' = lift' . elements++-- | Lifting of 'oneof'.++oneof' :: [MakeResult a] -> MakeResult a+oneof' mrs = withPMs $ \pms -> oneof $ map (\mr -> run mr pms) mrs++-- | Lifting of 'frequency'.++frequency' :: [(Int, MakeResult a)] -> MakeResult a+frequency' freqs = withPMs $ \pms ->+ frequency $ map (id *** flip run pms) freqs++-- | Lifting of 'sized'.++sized' :: (Int -> MakeResult a) -> MakeResult a+sized' mr = withPMs $ \pms -> sized (\size -> run (mr size) pms)++-- | Lifting of 'resize'.++resize' :: Int -> MakeResult a -> MakeResult a+resize' n mr = withPMs $ \pms -> resize n (run mr pms)++------------------------------------------------------------------------+-- Some predefined generators++-- | An implementation of @'MakeResult' a@ which is suitable when @a@+-- is flat and has an 'Arbitrary' instance. Yields bottoms around 10%+-- of the time.++flat :: Arbitrary a => MakeResult a+flat = transform $+ frequency' [ (1, return bottom)+ , (9, arbitrary')+ ]++-- | This 'MakeResult' yields finite partial lists.++finiteListOf :: MakeResult a -> MakeResult [a]+finiteListOf makeResult = sized' list+ where+ list size = transform $+ if size == 0 then+ baseCase+ else+ frequency' [ (1, baseCase)+ , (9, liftM2 (:) makeResult (list (size - 1)))+ ]++ baseCase =+ frequency' [(1, return bottom), (1, return [])]++-- | This 'MakeResult' yields infinite partial lists.++infiniteListOf :: MakeResult a -> MakeResult [a]+infiniteListOf makeResult = transform $+ liftM2 (:) makeResult (infiniteListOf makeResult)++-- | This 'MakeResult' yields finite or infinite partial lists.++listOf :: MakeResult a -> MakeResult [a]+ -- Not really necessary to have a transform here...+listOf makeResult = transform $+ oneof' [ finiteListOf makeResult+ , infiniteListOf makeResult+ ]++------------------------------------------------------------------------+-- Failed attempt at a generic implementation of MakeResult++-- Main problem: Getting the frequencies right. Lists are very short+-- right now.++-- Other problem: Int and Float.++-- Further remark: We need finite and infinite versions of this+-- function.++makeResult :: forall a. Data a => MakeResult a+makeResult = transform (frequency' $ (1, return bottom) : others)+ where+ others = case dataTypeRep (dataTypeOf (undefined :: a)) of+ AlgRep constrs ->+ map (handle (L.genericLength constrs)) constrs+ IntRep -> [(9, cast' (arbitrary' :: MakeResult Integer))]+ FloatRep -> [(9, cast' (arbitrary' :: MakeResult Double))]+ StringRep -> nonBottomError "makeResult: StringRep."+ NoRep -> nonBottomError "makeResult: NoRep."++ handle noConstrs con =+ (freq, fromConstrM makeResult con :: MakeResult a)+ where noArgs = glength (fromConstr con :: a)+ -- Aim for at most 10% bottoms (on average).+ freq = 1 `max` ceiling (9 / noConstrs)++ cast' gen = flip fmap gen $ \x -> case cast x of+ Just x' -> x'+ Nothing -> nonBottomError $+ "makeResult: Cannot handle Int and Float." +++ " Use Integer or Double instead."
+ Test/ChasingBottoms/ContinuousFunctions/Tests.hs view
@@ -0,0 +1,219 @@+{-# OPTIONS -fglasgow-exts #-}++-- TODO: Tests passed even though for finiteTreeOf and finiteListOf+-- transform was only applied once at the top-level!++-- | Tests for "Test.ChasingBottoms.ContinuousFunctions". So far the+-- tests are rather weak.++module Test.ChasingBottoms.ContinuousFunctions.Tests (tests) where++import Test.ChasingBottoms.ContinuousFunctions+import Test.ChasingBottoms.IsBottom+import Test.ChasingBottoms.SemanticOrd+import qualified Test.ChasingBottoms.TestUtilities.Generators as Gen+import Test.ChasingBottoms.TestUtilities.Generators (Tree(..))+import Test.ChasingBottoms.ApproxShow+import Data.Generics+import Test.QuickCheck+import Test.QuickCheck.Batch (run, TestOptions(..), TestResult(..))+import Test.ChasingBottoms.TestUtilities+import Control.Monad+import Data.List+import Data.Ratio++------------------------------------------------------------------------+-- Example data type++finiteTreeOf :: MakeResult a -> MakeResult (Tree a)+finiteTreeOf makeResult = sized' tree+ where+ tree size = transform $+ if size == 0 then+ baseCase+ else+ frequency' [ (1, baseCase)+ , (1, liftM2 Branch tree' tree')+ ]+ where+ tree' = tree (size `div` 2)++ baseCase =+ frequency' [ (1, return bottom)+ , (2, liftM Leaf makeResult)+ ]++------------------------------------------------------------------------+-- Helpers++integer :: Gen Integer+integer = frequency [ (1, return bottom)+ , (9, arbitrary)+ ]++length' :: Num b => [a] -> b+length' xs | isBottom xs = 0+length' [] = 1+length' (x:xs) = 1 + length' xs++depth :: (Ord b, Num b) => Tree a -> b+depth t | isBottom t = 0+depth (Leaf {}) = 1+depth (Branch l r) = 1 + (depth l `max` depth r)++------------------------------------------------------------------------+-- Tests++-- Interesting properties for the function generators:+--+-- * Surjectivity.+--+-- * Decent distribution.+--+-- How do we test these properties?++testDistribution test t = do+ result <- run t testOptions+ let (ok, msg) = apply test result+ unless ok $ putStrLn msg+ return ok+ where+ apply test (TestOk _ n args) = test n args+ apply _ _ = (False, "Test failed.")++ testOptions = TestOptions { no_of_tests = 1000+ , length_of_tests = 0 -- No time limit.+ , debug_tests = False+ }+++spread n args = (uniqueShare >= 3%4, "uniqueShare: " ++ show uniqueShare)+ where noUniqueArgs = length . group . sort $ args+ uniqueShare = noUniqueArgs % n++len max avg short n args =+ ( maxLen >= max && averageLen >= avg && shortShare >= 1%10+ , "maxLen: " ++ show maxLen +++ ", averageLen: " ++ show averageLen +++ ", shortShare: " ++ show shortShare+ )+ where maxLen = maximum lengths+ averageLen = sum lengths % noArgs+ noShortLists = genericLength (filter (<= short) lengths)+ lengths = map read . concat $ args :: [Integer]+ noArgs = toInteger n+ shortShare = noShortLists % noArgs++-- | We want to make sure that we can generate many different kinds of+-- lazy functions.++prop_many_functions_rather_lazy = testDistribution spread $+ forAll (functionTo (finiteTreeOf (finiteTreeOf flat))) $+ \(f :: Tree Integer -> Tree (Tree Bool)) ->+ f bottom /=! bottom && f (Leaf bottom) <! f (Leaf 1) ==>+ collect (map (approxShow 100 . f) [bottom, Leaf bottom, Leaf 1]) $+ True++-- | The generated lists should not be too short.++prop_lists_have_decent_length = testDistribution (len 20 6 5) $+ forAll (functionTo (finiteListOf flat)) $ \(f :: Integer -> [Bool]) ->+ forAll integer $ \(i :: Integer) ->+ collect (length' (f i) :: Integer) $+ True++-- | The generated trees should not be too shallow.++prop_trees_have_decent_depth = testDistribution (len 6 2 2) $+ forAll (functionTo (finiteTreeOf flat)) $ \(f :: Integer -> Tree Bool) ->+ forAll integer $ \(i :: Integer) ->+ collect (depth (f i) :: Integer) $+ True++-- | In one version of Data.Generics the following equations were+-- valid:+--+-- * @'toConstr' ('bottom' :: ()) = 'toConstr' ()@+--+-- * @'toConstr' ('bottom' :: One) = _|_@+--+-- 'toConstr' should be strict. There is a workaround for this (using+-- seq) in "Test.ChasingBottoms.ContinuousFunctions", and the+-- following two tests check that this workaround works.++data One+ = One+ deriving (Typeable, Data)++prop_some_lazy_unit =+ forAll (functionTo (finiteTreeOf flat)) $ \(f :: () -> Tree Bool) ->+ f bottom <! f () ==>+ True++prop_some_lazy_One =+ forAll (functionTo (finiteTreeOf flat)) $ \(f :: One -> Tree Bool) ->+ f bottom <! f One ==>+ True++-- | Example from documentation. Here mostly to check that it type+-- checks.++prop_example_works =+ forAll (functionTo (finiteTreeOf flat)) $+ \(f :: Bool -> Tree Integer) ->+ f bottom <=! f True && f bottom <=! f False++-- | Generated functions should be monotone.++prop_functions_monotone =+ forAll (functionTo (finiteListOf flat))+ $ \(f :: Tree Integer -> [Bool]) ->+ forAll (pair (Gen.finiteTreeOf Gen.integer)+ (Gen.geTreeOf Gen.integer Gen.geInteger Gen.finiteTreeOf))+ $ \(x, y) ->+ x <=! y && f x <=! f y++------------------------------------------------------------------------+-- | All tests collected together.++tests :: IO Bool+tests = do+ b1 <- fmap and $ sequence theIOTests+ b2 <- runQuickCheckTests $ map run $ concat theTests+ return (b1 && b2)+ where+ theIOTests :: [IO Bool]+ theIOTests = [ prop_many_functions_rather_lazy+ , prop_lists_have_decent_length+ , prop_trees_have_decent_depth+ ]++ theTests :: [[Property]]+ theTests = [ [ prop_example_works+ , prop_some_lazy_unit+ , prop_some_lazy_One+ , prop_functions_monotone+ ]+ ]++------------------------------------------------------------------------+-- Manual inspection of function tables++viewFun :: (ApproxShow b, Data a) => MakeResult b -> [a] -> IO ()+viewFun (makeResult :: MakeResult b) (inputs :: [a]) = test $+ forAll (functionTo makeResult) $ \(f :: a -> b) ->+ collect (map (approxShow 5 . f) inputs) $ True++bool = undefined :: Bool+int = undefined :: Int+float = undefined :: Float+treeOfBool = undefined :: Tree Bool++test0 = viewFun (flat :: MakeResult Bool) [bottom, False, True]+test1 = viewFun (finiteTreeOf flat :: MakeResult (Tree Bool))+ [bottom, False, True]+test2 = viewFun (finiteTreeOf flat :: MakeResult (Tree Bool))+ [bottom, Leaf bottom, Leaf False]++test4 = viewFun (flat :: MakeResult Int) [bottom, False, True]+test5 = viewFun (flat :: MakeResult Float) [bottom, False, True]
+ Test/ChasingBottoms/IsBottom.hs view
@@ -0,0 +1,103 @@+-- |+-- Module : Test.ChasingBottoms.IsBottom+-- Copyright : (c) Nils Anders Danielsson 2004-2007+-- License : See the file LICENCE.+-- +-- Maintainer : http://www.cs.chalmers.se/~nad/+-- Stability : experimental+-- Portability : non-portable (exceptions)+--++module Test.ChasingBottoms.IsBottom+ ( isBottom+ , bottom+ , nonBottomError+ , isBottomTimeOut+ ) where++import Prelude hiding (catch)+import Control.Exception (catch, throw, Exception(..), evaluate)+import System.IO.Unsafe (unsafePerformIO)+import qualified Test.ChasingBottoms.TimeOut as T++-- | @'isBottom' a@ returns 'False' if @a@ is distinct from bottom. If+-- @a@ equals bottom and results in an exception which is caught by+-- 'isBottom', and this exception is of a certain kind (see below),+-- then @'isBottom' a = 'True'@. Other caught exceptions are+-- re-thrown. If @a@ never reaches a weak head normal form and+-- never throws an exception, then @'isBottom' a@ never terminates.+--+-- The exceptions that yield 'True' are those that correspond to+-- \"pure bottoms\", i.e. bottoms that can originate in pure code.+-- Assertions are excluded, since their behaviour depends on compiler+-- flags (not pure, and a failed assertion should really yield an+-- exception and nothing else). The same applies to arithmetic+-- exceptions (machine dependent, except possibly for+-- 'Control.Exception.DivideByZero', but the value infinity makes that+-- case unclear as well).++-- Should we use throw or throwIO below?+-- It doesn't seem to matter, and I don't think it matters, but+-- using throw won't give us any problems.++-- Check out a discussion about evaluate around+-- http://www.haskell.org/pipermail/glasgow-haskell-users/2002-May/003393.html.++-- From the docs:+-- evaluate undefined `seq` return () ==> return ()+-- catch (evaluate undefined) (\e -> return ()) ==> return ()++isBottom :: a -> Bool+isBottom = isBottomTimeOut Nothing++-- | 'bottom' generates a bottom that is suitable for testing using+-- 'isBottom'.+bottom :: a+bottom = error "_|_"++-- | @'nonBottomError' s@ raises an exception ('AssertionFailed') that+-- is not caught by 'isBottom'. Use @s@ to describe the exception.++nonBottomError :: String -> a+nonBottomError = throw . AssertionFailed++-- | @'isBottomTimeOut' timeOutLimit@ works like 'isBottom', but if+-- @timeOutLimit@ is @'Just' lim@, then computations taking more than+-- @lim@ seconds are also considered to be equal to bottom. Note that+-- this is a very crude approximation of what a bottom is. Also note+-- that this \"function\" may return different answers upon different+-- invocations. Take it for what it is worth.+--+-- 'isBottomTimeOut' is subject to all the same scheduling vagaries as+-- 'Test.ChasingBottoms.TimeOut.timeOut'.++isBottomTimeOut :: Maybe Int -> a -> Bool+isBottomTimeOut timeOutLimit f = unsafePerformIO $+ maybeTimeOut (evaluate f) `catch` \e -> case e of+ ArithException _ -> throw e+ ArrayException _ -> return True+ AssertionFailed _ -> throw e+ AsyncException _ -> throw e+ BlockedOnDeadMVar -> throw e+ Deadlock -> throw e+ DynException _ -> throw e+ ErrorCall _ -> return True+ ExitException _ -> throw e+ IOException _ -> throw e+ NoMethodError _ -> return True+ NonTermination -> return True+ PatternMatchFail _ -> return True+ RecConError _ -> return True+ RecSelError _ -> return True+ RecUpdError _ -> return True+ where+ maybeTimeOut io = case timeOutLimit of+ Nothing -> do+ io+ return False+ Just lim -> do+ result <- T.timeOut lim io+ case result of -- Note that evaluate bottom /= bottom.+ T.Value _ -> return False+ T.NonTermination -> return True+ T.Exception e -> throw e -- Catch the exception above.
+ Test/ChasingBottoms/IsBottom/Tests.hs view
@@ -0,0 +1,79 @@+-- | Tests of the functions in "Test.ChasingBottoms.IsBottom".+--+-- Note that the warnings given when compiling this module are+-- intentional. See the internal comments for more information.++module Test.ChasingBottoms.IsBottom.Tests (tests) where++import Test.ChasingBottoms.IsBottom+import System.IO.Unsafe+import Data.Array+import System.Exit+import qualified Control.Exception as E++isException f = unsafePerformIO $+ (E.evaluate f >> return False) `E.catch` const (return True)++bot = bot+notbot x = notbot x++data T' a = L' | B' (T' a) (T' a) deriving Eq++instance Monad T'++leftInfinite' = B' leftInfinite' L'++infiniteRecursion = leftInfinite' == leftInfinite'++data A2 = A2 { aaa :: A2 } | C { ccc :: A2 }++tests :: [Bool]+tests =+ -- Basic cases.+ [ isBottom bottom+ , isBottom undefined+ , isBottom (error "...")+ -- This sometimes leads to a stack overflow.+ -- , isBottom bot++ -- const bottom /= bottom.+ , not (isBottom notbot)+ , not (isBottom (const bottom))++ -- Other types also lifted.+ , not (isBottom (bottom, bottom))+ , not (isBottom (Just bottom))++ -- Pattern match failure.+ , isBottom (let (x, y) = bottom in x :: Bool)+ , isBottom (let Just x = Nothing in x :: Char)++ -- Nonterminating, but not bottom.+ , not (isBottom [1..])++ -- Missing methods.+ -- Skip this test to avoid compiler warnings.+ , isBottom (L' >> L')++ -- Array stuff.+ , isBottom (array (1,0) [] ! 0)+ , isBottom (array (0,0) [] ! 0)++ -- Record stuff.+ -- Skip the first one to avoid compiler warnings.+ , isBottom (let x = A2 {} in aaa x)+ , isBottom (let x = A2 { aaa = x } in ccc x)+ , isBottom (let x = A2 { aaa = x } in x { ccc = x })++ -- Infinite recursion, no data produced, should yield stack+ -- overflow...+ -- Not a quick test (on some machines, anyway). And the result+ -- might be optimisation dependent.+ -- , isException (isBottom infiniteRecursion)++ -- Some other exceptions that are not caught, including+ -- nonBottomError.+ , isException (isBottom (unsafePerformIO $ exitWith ExitSuccess))+ , isException (isBottom (1 `div` 0))+ , isException (nonBottomError "...")+ ]
+ Test/ChasingBottoms/IsType.hs view
@@ -0,0 +1,41 @@+-- |+-- Module : Test.ChasingBottoms.IsType+-- Copyright : (c) Nils Anders Danielsson 2004-2007+-- License : See the file LICENCE.+-- +-- Maintainer : http://www.cs.chalmers.se/~nad/+-- Stability : experimental+-- Portability : non-portable (GHC-specific)+--+-- Internal helper functions.++module Test.ChasingBottoms.IsType+ ( isFunction+ , isTuple+ , isList+ , isString+ ) where++import Data.Typeable++-- | '@isFunction@ f' returns 'True' iff the top level \"constructor\"+-- of @f@ is a function arrow.+isFunction :: Typeable a => a -> Bool+isFunction f = con f == con not -- TyCon is abstract.++con :: Typeable a => a -> TyCon+con = typeRepTyCon . typeOf++-- | This function is rather fragile, but should be OK. It is only+-- used by "Test.ChasingBottoms.ApproxShow", which should only be used+-- for debugging purposes anyway. The unit type is not considered to+-- be a tuple.+isTuple :: Typeable a => a -> Bool+isTuple x = if null s then False else head s == ','+ where s = tyConString (con x)++isString :: Typeable a => a -> Bool+isString x = isList x && typeRepArgs (typeOf x) == typeRepArgs (typeOf "")++isList :: Typeable a => a -> Bool+isList x = con x == con ""
+ Test/ChasingBottoms/IsType/Tests.hs view
@@ -0,0 +1,26 @@+-- | Tests of the functions in "Test.ChasingBottoms.IsType".++module Test.ChasingBottoms.IsType.Tests (tests) where++import Test.ChasingBottoms.IsType++tests :: [Bool]+tests =+ -- isFunction identifies functions.+ [ isFunction (id :: Char -> Char) == True+ , isFunction ((==) :: Char -> Char -> Bool) == True+ , isFunction 'c' == False+ , isFunction [not] == False++ , isTuple [not] == False+ , isTuple () == False+ , isTuple ('a', 'c') == True++ , isList "" == True+ , isList [not] == True+ , isList ('a', 'c') == False++ , isString "" == True+ , isString [not] == False+ , isString ('a', 'c') == False+ ]
+ Test/ChasingBottoms/Nat.hs view
@@ -0,0 +1,109 @@+{-# OPTIONS -fglasgow-exts #-}++-- |+-- Module : Test.ChasingBottoms.Nat+-- Copyright : (c) Nils Anders Danielsson 2004-2007+-- License : See the file LICENCE.+-- +-- Maintainer : http://www.cs.chalmers.se/~nad/+-- Stability : experimental+-- Portability : non-portable (GHC-specific)+--+-- A simple implementation of natural numbers on top of 'Integer's.+-- Note that since 'Integer's are used there is no infinite natural+-- number; in other words, 'succ' is strict.++module Test.ChasingBottoms.Nat(Nat, isSucc, fromSucc, natrec, foldN) where++import Test.QuickCheck+import Data.Ratio ((%))+import Data.Typeable++default ()++-- | Natural numbers.+--+-- No 'Data.Generics.Basics.Data' instance is provided since the+-- implementation should be abstract.++-- Could add 'Data.Generics.Basics.Data' instance based on unary+-- representation of natural numbers, but that would lead to+-- inefficiencies.+newtype Nat = Nat { nat2int :: Integer } deriving (Eq, Ord, Typeable)++-- | @'isSucc' 0 == 'False'@, for other total natural numbers it is 'True'.+isSucc :: Nat -> Bool+isSucc (Nat 0) = False+isSucc _ = True++-- | @'fromSucc' 0 == 'Nothing'@, @'fromSucc' (n+1) == 'Just' n@ for a+-- total natural number @n@.+fromSucc :: Nat -> Maybe Nat+fromSucc (Nat 0) = Nothing+fromSucc n = Just $ pred n++-- | 'natrec' performs primitive recursion on natural numbers.+natrec :: a -> (Nat -> a -> a) -> Nat -> a+natrec g _ (Nat 0) = g+natrec g h n = let p = pred n in h p (natrec g h p)++-- | 'foldN' is a fold on natural numbers:+--+-- @+-- 'foldN' g h = 'natrec' g ('curry' '$' h . 'snd')+-- @+foldN :: a -> (a -> a) -> Nat -> a+foldN g h = natrec g (curry $ h . snd)++steal :: (Integer -> Integer -> Integer) -> Nat -> Nat -> Nat+steal op x y = fromInteger $ (nat2int x) `op` (nat2int y)++instance Num Nat where+ (+) = steal (+)+ (*) = steal (*)+ x - y = let x' = nat2int x; y' = nat2int y+ in if x' < y' then+ error "Nat: x - y undefined if y > x."+ else+ fromInteger $ x' - y'+ negate = error "Nat: negate undefined."+ signum n = if isSucc n then 1 else 0+ abs = id+ fromInteger i | i < 0 = error "Nat: No negative natural numbers."+ | otherwise = Nat i++instance Real Nat where+ toRational = (%1) . nat2int++steal2 :: (Integer -> Integer -> (Integer, Integer))+ -> Nat -> Nat -> (Nat, Nat)+steal2 op x y = let (x', y') = (nat2int x) `op` (nat2int y)+ in (fromInteger x', fromInteger y')++instance Integral Nat where+ toInteger = toInteger . fromEnum+ a `quotRem` b = if b == 0 then+ error "Nat: quotRem undefined for zero divisors."+ else+ steal2 quotRem a b+ a `divMod` b = if b == 0 then+ error "Nat: divMod undefined for zero divisors."+ else+ steal2 divMod a b++instance Enum Nat where+ succ = (+ 1)+ pred = subtract 1+ toEnum = fromInteger . toInteger+ fromEnum = fromInteger . nat2int+ -- Add tests for enumFrom and friends if the default definitions are+ -- overridden.++instance Show Nat where+ showsPrec _ = showString . show . nat2int++instance Arbitrary Nat where+ arbitrary = do+ n <- arbitrary :: Gen Integer+ return $ fromInteger $ abs n+ coarbitrary n = coarbitrary (toInteger n)
+ Test/ChasingBottoms/Nat/Tests.hs view
@@ -0,0 +1,239 @@+{-# OPTIONS -fglasgow-exts #-}++-- | Tests for "Test.ChasingBottoms.Nat".++-- The automatically derived 'Typeable' instance is not tested.++module Test.ChasingBottoms.Nat.Tests (tests) where++import Test.ChasingBottoms.Nat+import Test.ChasingBottoms.SemanticOrd+import Test.ChasingBottoms.TestUtilities+import Test.QuickCheck+import Test.QuickCheck.Batch+import Data.Maybe+import Data.List+import Data.Ratio++default ()++-- The default versions of succ and pred go via Ints, and hence+-- perform incorrectly in the presence of large natural numbers. Hence+-- this generator is needed. Other tests can possibly also fail in the+-- presence of large natural numbers, but QuickCheck does not handle+-- large numbers very well, especially not when coarbitrary is used,+-- so we do not use this generator for all tests. Furthermore+-- defaulting is turned off here and in Test.ChasingBottoms.Nat, and+-- that should minimise surprises.++largeNat :: Gen Nat+largeNat = do+ n <- choose (0, 2 * toInteger (maxBound :: Int))+ return (fromInteger n)++-- Testing isSucc.++prop_isSucc n = isSucc n == (n > 0)++-- Testing fromSucc.++prop_fromSucc n | n == 0 = fromSucc n == Nothing+ | otherwise = fromSucc n == Just (n-1)++-- Testing natrec.++-- How do you test something as versatile as natrec? Well, at least we+-- can verify that we can use it to implement addition.++prop_natrec_add m n = natrec m (\_ o -> succ o) n == m + n++-- There is no need to test foldN, since it is specified by its+-- definition.++-- Testing Enum.++prop_Nat_Enum_succ =+ forAll largeNat $ \n ->+ succ n == n + 1+prop_Nat_Enum_pred =+ forAll largeNat $ \n ->+ n > 0 ==> pred n == n - 1++prop_Nat_Enum_toEnum (n :: Int) =+ n >= 0 ==> (toEnum n :: Nat) == fromInteger (toInteger n)+prop_Nat_Enum_fromEnum (n :: Nat) =+ n <= fromInteger (toInteger (maxBound :: Int)) ==>+ toInteger (fromEnum n) == toInteger n++-- enumFrom and friends have default definitions.++-- Testing Eq.++prop_Nat_Eq_congruence =+ eqIsCongruence arbitrary equalTo notEqualTo+ (arbitrary :: Gen (Nat -> Integer))++equalTo (n :: Nat) = return n++notEqualTo (n :: Nat) = do+ m <- fmap succ arbitrary -- m >= 1.+ if m <= n then+ elements [n - m, n + m]+ else+ return (n + m)++-- Testing Show.++prop_Nat_Show (m :: Nat) = show m == show (toInteger m)++-- Testing Ord.++prop_Nat_Ord_total_order = ordIsTotalOrder arbitrary+ equalTo notEqualTo greaterThanOrEqual++greaterThanOrEqual (n :: Nat) = do+ m <- arbitrary+ return (n + m)++-- Testing Num.++prop_Nat_mul_iterated_sum (m :: Nat) n =+ m * n == foldr (+) 0 (genericReplicate m n)++prop_Nat_plus_assoc (m :: Nat) n o = m + (n + o) == (m + n) + o+prop_Nat_plus_comm (m :: Nat) n = m + n == n + m++prop_Nat_mul_assoc (m :: Nat) n o = m * (n * o) == (m * n) * o+prop_Nat_mul_comm (m :: Nat) n = m * n == n * m++prop_Nat_mul_plus_left_dist (m :: Nat) n o = m * (n + o) == m * n + m * o++prop_Nat_mul_plus_zero (m :: Nat) = m + 0 == m+prop_Nat_mul_mul_unit (m :: Nat) = m * 1 == m++prop_Nat_minus n =+ forAll (greaterThanOrEqual n) $ \m ->+ (m - n) + n == m++prop_Nat_signum_abs (m :: Nat) = signum m * abs m == m+prop_Nat_signum_zero = (signum 0 :: Nat) == 0++prop_Nat_fromInteger_plus m n =+ m >= 0 && n >= 0 ==>+ fromInteger m + fromInteger n == (fromInteger (m + n) :: Nat)+prop_Nat_fromInteger_mul m n =+ m >= 0 && n >= 0 ==>+ fromInteger m * fromInteger n == (fromInteger (m * n) :: Nat)++-- negate is undefined.++-- Testing Integral.++prop_Nat_to_from (m :: Nat) = fromInteger (toInteger m) == m+prop_Nat_from_to i = i >= 0 ==> toInteger (fromInteger i :: Nat) == i++prop_Nat_quotRem (m :: Nat) n =+ n /= 0 ==> m `quotRem` n == (m `quot` n, m `rem` n)+prop_Nat_divMod (m :: Nat) n =+ n /= 0 ==> m `divMod` n == (m `div` n, m `mod` n)++prop_Nat_quot_rem (m :: Nat) n =+ n /= 0 ==> (m `quot` n) * n + m `rem` n == m+prop_Nat_div_mod (m :: Nat) n =+ n /= 0 ==> (m `div` n) * n + m `mod` n == m++-- Testing Real.++prop_Nat_toRational (m :: Nat) = toRational m == toInteger m % 1++-- Since the implementation is based on Integers I'd like to test that+-- we can't construct values of the form "Nat i" where i is a negative+-- Integer. (This can be seen as a test of the observation function+-- toInteger.)++prop_Nat_closed = [ unary (fromJust . fromSucc)+ -- Ord+ , binary max+ , binary min+ -- Enum+ -- enumFrom and friends have default definitions.+ , unary succ+ , unary pred+ , unary' toEnum+ -- Num+ , binary (+)+ , binary (-)+ , binary (*)+ , unary negate+ , unary abs+ , unary signum+ , unary' fromInteger+ -- Integral+ , binary quot+ , binary rem+ , binary div+ , binary mod+ , binary (fst .^^ quotRem)+ , binary (snd .^^ quotRem)+ , binary (fst .^^ divMod)+ , binary (snd .^^ divMod)+ ]+ where+ ok (n :: Nat) = (toInteger n >= 0) <=! True++ unary (f :: Nat -> Nat) = unary' f++ unary' f =+ forAll arbitrary $ \x ->+ ok (f x)++ binary f =+ forAll arbitrary $ \(m :: Nat) ->+ forAll arbitrary $ \(n :: Nat) ->+ ok (f m n)++ f .^^ g = \x y -> f (g x y)++-- | All tests collected together.++tests :: IO Bool+tests = runQuickCheckTests theTests+ where+ theTests = map run (concat testLists) ++ singleTests++ singleTests =+ [ run prop_isSucc+ , run prop_fromSucc+ , run prop_natrec_add+ , run prop_Nat_Enum_succ+ , run prop_Nat_Enum_pred+ , run prop_Nat_Enum_toEnum+ , run prop_Nat_Enum_fromEnum+ , run prop_Nat_Show+ , run prop_Nat_mul_iterated_sum+ , run prop_Nat_plus_assoc+ , run prop_Nat_plus_comm+ , run prop_Nat_mul_assoc+ , run prop_Nat_mul_comm+ , run prop_Nat_mul_plus_left_dist+ , run prop_Nat_mul_plus_zero+ , run prop_Nat_mul_mul_unit+ , run prop_Nat_minus+ , run prop_Nat_signum_abs+ , run prop_Nat_signum_zero+ , run prop_Nat_fromInteger_plus+ , run prop_Nat_fromInteger_mul+ , run prop_Nat_to_from+ , run prop_Nat_from_to+ , run prop_Nat_quotRem+ , run prop_Nat_divMod+ , run prop_Nat_quot_rem+ , run prop_Nat_div_mod+ , run prop_Nat_toRational+ ]++ testLists =+ [ prop_Nat_Eq_congruence+ , prop_Nat_Ord_total_order+ , prop_Nat_closed+ ]
+ Test/ChasingBottoms/SemanticOrd.hs view
@@ -0,0 +1,253 @@+{-# OPTIONS -fglasgow-exts -fallow-undecidable-instances #-}++-- |+-- Module : Test.ChasingBottoms.SemanticOrd+-- Copyright : (c) Nils Anders Danielsson 2004-2007+-- License : See the file LICENCE.+-- +-- Maintainer : http://www.cs.chalmers.se/~nad/+-- Stability : experimental+-- Portability : non-portable (GHC-specific)+--+-- Generic semantic equality and order. The semantic order referred+-- to is that of a typical CPO for Haskell types, where e.g. @('True',+-- 'bottom') '<=!' ('True', 'False')@, but where @('True', 'True')@+-- and @('True', 'False')@ are incomparable.+--+-- The implementation is based on 'isBottom', and has the same+-- limitations. Note that non-bottom functions are not handled by any+-- of the functions described below.+--+-- One could imagine using QuickCheck for testing equality of+-- functions, but I have not managed to tweak the type system so that+-- it can be done transparently.++module Test.ChasingBottoms.SemanticOrd+ ( Tweak(..)+ , noTweak+ , SemanticEq(..)+ , SemanticOrd(..)+ ) where++import Data.Generics+import Test.ChasingBottoms.IsBottom+import Test.ChasingBottoms.IsType+import qualified Data.Maybe as Maybe+import Test.ChasingBottoms.Nat+import Test.ChasingBottoms.Approx++infix 4 <!, <=!, ==!, >=!, >!, /=!+infix 5 \/!+infixl 5 /\!++-- | The behaviour of some of the functions below can be tweaked.++data Tweak = Tweak+ { approxDepth :: Maybe Nat+ -- ^ If equal to @'Just' n@, an @'approxAll' n@ is performed on+ -- all arguments before doing whatever the function is supposed to+ -- be doing.+ , timeOutLimit :: Maybe Int+ -- ^ If equal to @'Just' n@, then all computations that take more+ -- than @n@ seconds to complete are considered to be equal to+ -- 'bottom'. This functionality is implemented using+ -- 'isBottomTimeOut'.+ }+ deriving (Eq, Ord, Show)++-- | No tweak (both fields are 'Nothing').++noTweak :: Tweak+noTweak = Tweak+ { approxDepth = Nothing+ , timeOutLimit = Nothing+ }++-- | 'SemanticEq' contains methods for testing whether two terms are+-- semantically equal.++-- Note that we only allow a -> a -> Bool here, not a -> b ->+-- Bool. Otherwise we would allow behaviour like the following:+-- > (bottom : bottom :: [Int]) <=!! ("tr" :: String)+-- True++class SemanticEq a where+ (==!), (/=!) :: a -> a -> Bool+ semanticEq :: Tweak -> a -> a -> Bool++ (/=!) = \x y -> not (x ==! y)+ (==!) = semanticEq noTweak++-- | 'SemanticOrd' contains methods for testing whether two terms are+-- related according to the semantic domain ordering.++class SemanticEq a => SemanticOrd a where+ (<!), (<=!), (>=!), (>!) :: a -> a -> Bool++ semanticCompare :: Tweak -> a -> a -> Maybe Ordering+ -- ^ @'semanticCompare' tweak x y@ returns 'Nothing' if @x@ and @y@ are+ -- incomparable, and @'Just' o@ otherwise, where @o :: 'Ordering'@+ -- represents the relation between @x@ and @y@.++ (\/!) :: a -> a -> Maybe a+ (/\!) :: a -> a -> a+ semanticJoin :: Tweak -> a -> a -> Maybe a+ semanticMeet :: Tweak -> a -> a -> a+ -- ^ @x '\/!' y@ and @x '/\!' y@ compute the least upper and greatest+ -- lower bounds, respectively, of @x@ and @y@ in the semantical+ -- domain ordering. Note that the least upper bound may not always+ -- exist.+ -- This functionality was implemented just because it was+ -- possible (and to provide analogues of 'max' and 'min' in the 'Ord'+ -- class). If anyone finds any use for it, please let me know.++ (>=!) = flip (<=!)+ (<!) = \x y -> x <=! y && x /=! y+ (>!) = \x y -> x >=! y && x /=! y++ x <=! y = case semanticCompare noTweak x y of+ Just LT -> True+ Just EQ -> True+ _ -> False++ (\/!) = semanticJoin noTweak+ (/\!) = semanticMeet noTweak++instance Data a => SemanticEq a where+ semanticEq tweak = liftAppr tweak semanticEq'++instance Data a => SemanticOrd a where+ semanticCompare tweak = liftAppr tweak semanticCompare'+ where+ semanticCompare' tweak x y =+ case ( semanticEq' tweak x y+ , semanticLE' tweak x y+ , semanticLE' tweak y x ) of+ (True, _, _) -> Just EQ+ (_, True, _) -> Just LT+ (_, _, True) -> Just Prelude.GT+ (_, _, _) -> Nothing+ semanticJoin tweak = liftAppr tweak semanticJoin'+ semanticMeet tweak = liftAppr tweak semanticMeet'++liftAppr :: (Data a, Data b) => Tweak -> (Tweak -> a -> a -> b) -> a -> a -> b+liftAppr tweak op x y = op tweak (appr x) (appr y)+ where appr = maybe id approxAll (approxDepth tweak)++------------------------------------------------------------------------++type Rel' = (Data a, Data b) => Tweak -> a -> b -> Bool+type Rel = (Data a, Data b) => a -> b -> Bool++semanticEq', semanticLE' :: Rel'++semanticEq' tweak a b = case ( isBottomTimeOut (timeOutLimit tweak) a+ , isBottomTimeOut (timeOutLimit tweak) b ) of+ (True, True) -> True+ (False, False) -> allOK (semanticEq' tweak) a b+ _ -> False++semanticLE' tweak a b = case ( isBottomTimeOut (timeOutLimit tweak) a+ , isBottomTimeOut (timeOutLimit tweak) b ) of+ (True, _) -> True+ (False, False) -> allOK (semanticLE' tweak) a b+ _ -> False++allOK :: Rel -> Rel+allOK op a b =+ -- It's really enough to test just a, since we restrict the types+ -- above, but why complicate things?+ if isFunction a || isFunction b then+ -- cast' a `fop` cast' b+ nonBottomError+ "The generic versions of (==!) and friends do not accept non-bottom \+ \functions."+ else+ a =^= b && childrenOK op a b++-- Check top-level. Note that this test always fails for "function+-- constructors".+(=^=) :: Rel+a =^= b = toConstr a == toConstr b++-- Check children.+childrenOK :: Rel -> Rel+childrenOK op = and .|.. gzipWithQ (\x y -> op x y)+ where f .|.. g = \x y -> f (g x y)++------------------------------------------------------------------------++semanticMeet' :: (Data a, Data b) => Tweak -> a -> b -> b+semanticMeet' tweak a (b :: b) =+ if isBottomTimeOut (timeOutLimit tweak) a ||+ isBottomTimeOut (timeOutLimit tweak) b then+ bottom+ else if isFunction a || isFunction b then+ nonBottomError "/\\! does not handle non-bottom functions."+ else if not (a =^= b) then+ bottom+ else+ gzipWithT (\x y -> semanticMeet' tweak x y) a b+ +semanticJoin' :: (Data a, Data b) => Tweak -> a -> b -> Maybe b+semanticJoin' tweak a (b :: b) =+ case ( isBottomTimeOut (timeOutLimit tweak) a+ , isBottomTimeOut (timeOutLimit tweak) b ) of+ (True, True) -> Just bottom+ (True, False) -> Just b+ (False, True) -> cast a+ (False, False)+ | isFunction a || isFunction b ->+ nonBottomError "\\/! does not handle non-bottom functions."+ | not (a =^= b) -> Nothing+ | otherwise -> gzipWithM (\x y -> semanticJoin' tweak x y) a b++------------------------------------------------------------------------++-- Variant of cast.++-- cast' :: (Typeable a, Typeable b) => a -> b+-- cast' = Maybe.fromJust . cast++------------------------------------------------------------------------++-- TODO: Implement a comparison operator which also works for functions.++-- newtype EqFun = EqFun { unEqFun ::+-- forall a b . (Data a, Data b) => a -> b -> Bool }++-- class SemanticFunEq a where+-- (!==!), (!/=!) :: a -> a -> Bool++-- (!/=!) = \x y -> not (x !==! y)++-- instance Data a => SemanticFunEq a where+-- x !==! y =+-- let test :: (Arbitrary b, Show b, Data c) =>+-- (b -> c1) -> (b -> c2) -> Bool+-- test f g = testIt (forAll arbitrary $ \(x :: b) -> f x !==!! g x)+-- in let ?funTest = EqFun test+-- in x !==!! y++-- (!==!!) :: (Data a, Data b, ?funTest :: EqFun) => a -> b -> Bool+-- x !==!! y = case (isBottom x, isBottom y) of+-- (True, True) -> True+-- (False, False) | isFunction x -> unEqFun ?funTest x y+-- | otherwise -> x =^= y && tmapQl (&&) True (!==!!) x y+-- _ -> False++-- This one works, but it only handles functions on the top level, not+-- functions inside e.g. lists.++-- instance (Show a, Arbitrary a, SemanticFunEq b) => SemanticFunEq (a -> b) where+-- f !==! g = case (isBottom f, isBottom g) of+-- (True, True) -> True+-- (False, False) -> testIt (forAll arbitrary $ \x -> f x !==! g x)+-- _ -> False++-- instance SemanticEq a => SemanticFunEq a where+-- a !==! b = case (isBottom a, isBottom b) of+-- (True, True) -> True+-- (False, False) -> -- We know that we are not dealing with functions.+-- a ==! b+-- _ -> False
+ Test/ChasingBottoms/SemanticOrd/Tests.hs view
@@ -0,0 +1,118 @@+{-# OPTIONS -fglasgow-exts #-}++-- | Tests for "Test.ChasingBottoms.SemanticOrd". The functions using+-- tweaks are currently not tested.++module Test.ChasingBottoms.SemanticOrd.Tests (tests) where++import Test.ChasingBottoms.SemanticOrd+import Test.ChasingBottoms.TestUtilities+import Test.ChasingBottoms.TestUtilities.Generators hiding (tests)+import Test.QuickCheck+import Test.QuickCheck.Batch (run)+import Data.Generics+import Control.Monad+import Data.Maybe++------------------------------------------------------------------------+-- The actual tests++prop_SemanticEq_congruence :: (Data a, Show a)+ => Gen a+ -> NotEqualGen a+ -> Cogen a+ -> [Property]+prop_SemanticEq_congruence element notEqualTo coGen =+ isCongruence element return notEqualTo (==!) (/=!)+ (function coGen integer) (==!)++prop_SemanticOrd_partial_order :: (Data a, Show a)+ => Gen a+ -> NotEqualGen a+ -> GreaterEqualGen a+ -> JoinableGen a+ -> [Property]+prop_SemanticOrd_partial_order element notEqualTo greaterThan joinable =+ isPartialOrder element return notEqualTo greaterThan (==!) (<=!) +++ isPartialOrderOperators element greaterThan (==!) (<=!) (<!) (>=!) (>!) +++ [ compare+ , meet_associative, meet_commutative, meet_idempotent, meet_lt+ , join_associative, join_commutative, join_idempotent, join_lt+ , join_meet_absorption, meet_join_absorption+ ]+ where+ twoElems = pair3 element greaterThan++ compare =+ forAll twoElems $ \(x, y) ->+ case semanticCompare noTweak x y of+ Nothing -> not (x <=! y) && not (x >=! y)+ Just LT -> x <! y+ Just EQ -> x ==! y+ Just Prelude.GT -> x >! y++ meet_associative = isAssociative (oneof [ liftM3 (,,) element element element+ , triple element joinable joinable+ ]+ )+ (==!) (/\!)+ meet_commutative = isCommutative (oneof [ liftM2 (,) element element+ , pair element joinable+ ]+ )+ (==!) (/\!)+ meet_idempotent = isIdempotent element (==!) (/\!)++ join_associative =+ forAll (triple element joinable joinable) $ \(x, y, z) ->+ (x \/! y >>= (\/! z)) ==! ((x \/!) =<< y \/! z)+ join_commutative = isCommutative (pair element joinable) (==!) (\/!)+ join_idempotent =+ forAll element $ \x ->+ x \/! x ==! Just x++ join_meet_absorption =+ forAll jmPair $ \(x, y) ->+ x \/! (x /\! y) ==! Just x+ where jmPair = oneof [ liftM2 (,) element element+ , pair element joinable+ ]+ meet_join_absorption =+ forAll (pair element joinable) $ \(x, y) ->+ x /\! fromJust (x \/! y) ==! x++ twoElems' = frequency [ (2, twoElems), (1, pair element joinable) ]++ meet_lt =+ forAll twoElems' $ \(x, y) ->+ (x <=! y) == (x /\! y ==! x)+ join_lt =+ forAll twoElems' $ \(x, y) ->+ (x <=! y) == (x \/! y ==! Just y)++-- | All tests collected together.++tests :: IO Bool+tests = runQuickCheckTests $ map run $ concat theTests+ where+ theTests =+ [ prop_SemanticEq_congruence bool neBool coBool+ , prop_SemanticEq_congruence integer neInteger coInteger+ , prop_SemanticEq_congruence (finiteListOf bool)+ (neListOf bool neBool finiteListOf)+ (coListOf coBool)+ , prop_SemanticEq_congruence (finiteTreeOf integer)+ (neTreeOf integer neInteger finiteTreeOf)+ (coTreeOf coInteger)+ , prop_SemanticOrd_partial_order bool neBool geBool joinBool+ , prop_SemanticOrd_partial_order integer neInteger geInteger joinInteger+ , prop_SemanticOrd_partial_order (finiteListOf bool)+ (neListOf bool neBool finiteListOf)+ (geListOf bool geBool finiteListOf)+ (joinListOf bool joinBool finiteListOf)+ , prop_SemanticOrd_partial_order (finiteTreeOf integer)+ (neTreeOf integer neInteger finiteTreeOf)+ (geTreeOf integer geInteger finiteTreeOf)+ (joinTreeOf integer joinInteger+ finiteTreeOf)+ ]
+ Test/ChasingBottoms/TestLibraryWhenCompiling.hs view
@@ -0,0 +1,21 @@+{-# OPTIONS -fth #-}++-- | By importing this module in e.g. "Test.ChasingBottoms" the+-- library refuses to be built if the tests fail.++module Test.ChasingBottoms.TestLibraryWhenCompiling () where++import qualified Test.ChasingBottoms.Tests as Tests+import qualified System.IO as IO+import qualified Language.Haskell.TH as TH++$(do + b <- TH.runIO $ do putStr "----- Testing the library. -----\n\n"+ b <- Tests.main+ IO.hFlush IO.stdout+ return b+ if not b then+ fail "Tests failed. Refusing to build library."+ else+ return []+ )
+ Test/ChasingBottoms/TestUtilities.hs view
@@ -0,0 +1,433 @@+-- | Some utilities that are part of the testing framework.++module Test.ChasingBottoms.TestUtilities+ ( -- * Batch execution of QuickCheck tests+ runQuickCheckTests+ -- * Various algebraic properties+ , isAssociative+ , isCommutative+ , isIdempotent+ -- ** Equivalence and congruence+ , isEquivalenceRelation+ , isCongruence+ , eqIsCongruence+ -- ** Partial and total orders+ , isPartialOrder+ , isTotalOrder+ , isPartialOrderOperators+ , isTotalOrderOperators+ , ordIsTotalOrder+ -- * Helper functions+ , pair+ , triple+ , pair3+ ) where++import Test.QuickCheck+import Test.QuickCheck.Batch+import Data.List+import Control.Arrow+import Control.Monad+import Text.Show.Functions++------------------------------------------------------------------------+-- Batch execution of QuickCheck tests++-- | Runs a bunch of QuickCheck tests, printing suitable information+-- to standard output. Returns 'True' if no tests fail. Note that a+-- test where the inputs are exhausted is considered to have+-- succeeded.++runQuickCheckTests :: [TestOptions -> IO TestResult]+ -- ^ Create the tests in this list from ordinary+ -- QuickCheck tests by using 'run'.+ -> IO Bool+runQuickCheckTests tests = do+ results <- mapM ($ testOptions) tests+ mapM_ (putStr . showTR) results+ return $ all ok $ results+ where+ ok (TestOk {}) = True+ ok (TestExausted {}) = True -- We treat this as OK since the+ -- distribution of test data is displayed.+ ok (TestFailed {}) = False+ ok (TestAborted {}) = False++ testOptions = TestOptions { no_of_tests = 1000+ , length_of_tests = 0 -- No time limit.+ , debug_tests = False+ }++ showTR (TestOk _ n args) =+ "OK, passed " ++ show n ++ " tests.\n" ++ showArgs args+ showTR (TestExausted _ n args) =+ "Arguments exhausted after " ++ show n ++ " tests.\n" ++ showArgs args+ showTR (TestFailed _ _) = "Test failed.\n"+ showTR (TestAborted _) = "Test resulted in exception.\n"++ showArgs :: [[String]] -> String+ showArgs args+ | all null args = ""+ | otherwise =+ unlines+ . map (indent . uncurry (++)+ . (formatNum *** (concat . intersperse ", ")))+ . sortBy (\x y -> compare (fst y) (fst x))+ . map (length &&& head) . group . sort+ $ args+ where indent = (" " ++)+ formatNum = flip shows ": "++------------------------------------------------------------------------+-- Testing various algebraic properties++-- | Test for associativity.++isAssociative+ :: Show a+ => Gen (a, a, a)+ -- ^ Generator for arbitrary elements, possibly related in some+ -- way to make the test more meaningful.+ -> (a -> a -> Bool)+ -- ^ Equality test.+ -> (a -> a -> a)+ -- ^ The operation.+ -> Property+isAssociative triple (==.) (+.) =+ forAll triple $ \(x, y, z) ->+ ((x +. y) +. z) ==. (x +. (y +. z))++-- | Test for commutativity.++isCommutative+ :: Show a+ => Gen (a, a)+ -- ^ Generator for arbitrary elements, possibly related in some+ -- way to make the test more meaningful.+ -> (b -> b -> Bool)+ -- ^ Equality test.+ -> (a -> a -> b)+ -- ^ The operation.+ -> Property+isCommutative pair (==.) (+.) =+ forAll pair $ \(x, y) ->+ (x +. y) ==. (y +. x)++-- | Test for idempotence.++isIdempotent+ :: Show a+ => Gen a+ -- ^ Generator for arbitrary element.+ -> (a -> a -> Bool)+ -- ^ Equality test.+ -> (a -> a -> a)+ -- ^ The operation.+ -> Property+isIdempotent element (==.) (+.) =+ forAll element $ \x ->+ (x +. x) ==. x++-- | Tests for an equivalence relation. Requires that the relation is+-- neither always false nor always true.++isEquivalenceRelation+ :: Show a+ => Gen a+ -- ^ Generator for arbitrary element.+ -> (a -> Gen a)+ -- ^ Generator for element equivalent to argument.+ -> (a -> Gen a)+ -- ^ Generator for element not equivalent to argument.+ -> (a -> a -> Bool)+ -- ^ The relation.+ -> [Property]+isEquivalenceRelation element equalTo notEqualTo (===) =+ [reflexive, symmetric1, symmetric2, transitive]+ where+ x /== y = not (x === y)++ reflexive = forAll element $ \x ->+ x === x++ symmetric1 = forAll (pair element equalTo) $ \(x, y) ->+ x === y && y === x++ symmetric2 = forAll (pair element notEqualTo) $ \(x, y) ->+ x /== y && y /== x++ transitive = forAll (pair element equalTo) $ \(x, y) ->+ forAll (equalTo y) $ \z ->+ x === z++-- | Tests for a congruence. Also tests that the negated relation is+-- the negation of the relation.++isCongruence+ :: (Show a, Eq b)+ => Gen a+ -- ^ Generator for arbitrary element.+ -> (a -> Gen a)+ -- ^ Generator for element equivalent to argument.+ -> (a -> Gen a)+ -- ^ Generator for element not equivalent to argument.+ -> (a -> a -> Bool)+ -- ^ The relation.+ -> (a -> a -> Bool)+ -- ^ The negated relation.+ -> Gen (a -> b)+ -- ^ Generator for functions.+ -> (b -> b -> Bool)+ -- ^ Equality for function result type.+ -> [Property]+isCongruence element equalTo notEqualTo (===) (/==) function (.===) =+ isEquivalenceRelation element equalTo notEqualTo (===)+ ++ [cong, eq_neq1, eq_neq2]+ where+ cong = forAll function $ \f ->+ forAll (pair element equalTo) $ \(x, y) ->+ f x .=== f y+ eq_neq1 = forAll (pair element equalTo) $ \(x, y) ->+ x === y && not (x /== y)+ eq_neq2 = forAll (pair element notEqualTo) $ \(x, y) ->+ not (x === y) && x /== y++-- | Test that an 'Eq' instance is a congruence.++eqIsCongruence+ :: (Show a, Eq a, Eq b)+ => Gen a+ -- ^ Generator for arbitrary element.+ -> (a -> Gen a)+ -- ^ Generator for element equivalent to argument.+ -> (a -> Gen a)+ -- ^ Generator for element not equivalent to argument.+ -> Gen (a -> b)+ -- ^ Generator for functions.+ -> [Property]+eqIsCongruence element equalTo notEqualTo function =+ isCongruence element equalTo notEqualTo (==) (/=) function (==)++-- | Tests for a partial order.++isPartialOrder+ :: Show a+ => Gen a+ -- ^ Generator for arbitrary element.+ -> (a -> Gen a)+ -- ^ Generator for element equal to argument, according to+ -- underlying equality relation.+ -> (a -> Gen a)+ -- ^ Generator for element different from argument, according to+ -- underlying equality relation.+ -> (a -> Gen a)+ -- ^ Generator for element greater than or equal to argument.+ -> (a -> a -> Bool)+ -- ^ Underlying equality relation.+ -> (a -> a -> Bool)+ -- ^ The relation.+ -> [Property]+isPartialOrder element equalTo differentFrom greaterThan (==.) (<=.) =+ [reflexive, antisymmetric1, antisymmetric2, transitive]+ where+ infix 4 ==., <=.++ reflexive =+ forAll element $ \x ->+ x <=. x++ antisymmetric1 =+ forAll (pair element equalTo) $ \(x, y) ->+ (x <=. y && y <=. x) && x ==. y++ antisymmetric2 =+ forAll (pair element differentFrom) $ \(x, y) ->+ not (x <=. y && y <=. x) && not (x ==. y)++ transitive = forAll (pair element greaterThan) $ \(x, y) ->+ forAll (greaterThan y) $ \z ->+ x <=. z++-- | Tests for a total order.++isTotalOrder+ :: Show a+ => Gen a+ -- ^ Generator for arbitrary element.+ -> (a -> Gen a)+ -- ^ Generator for element equal to argument, according to+ -- underlying equality relation.+ -> (a -> Gen a)+ -- ^ Generator for element different from argument, according to+ -- underlying equality relation.+ -> (a -> Gen a)+ -- ^ Generator for element greater than or equal to argument.+ -> (a -> a -> Bool)+ -- ^ Underlying equality relation.+ -> (a -> a -> Bool)+ -- ^ The relation.+ -> [Property]+isTotalOrder element equalTo differentFrom greaterThan (==.) (<=.) =+ isPartialOrder element equalTo differentFrom greaterThan (==.) (<=.)+ ++ [total]+ where+ infix 4 <=.++ total =+ forAll element $ \x ->+ forAll element $ \y ->+ x <=. y || y <=. x++-- | Tests relating various partial order operators. Does not include+-- any tests from 'isPartialOrder'.++isPartialOrderOperators+ :: Show a+ => Gen a+ -- ^ Generator for arbitrary element.+ -> (a -> Gen a)+ -- ^ Generator for element greater than or equal to argument.+ -> (a -> a -> Bool)+ -- ^ Equal.+ -> (a -> a -> Bool)+ -- ^ Less than or equal.+ -> (a -> a -> Bool)+ -- ^ Less than.+ -> (a -> a -> Bool)+ -- ^ Greater than or equal.+ -> (a -> a -> Bool)+ -- ^ Greater than.+ -> [Property]+isPartialOrderOperators element greaterThan (==.) (<=.) (<.) (>=.) (>.) =+ [lt_le, gt_ge, ge_le, lt_gt]+ where+ infix 4 ==., <=., <., >=., >.++ twoElems = pair3 element greaterThan++ lt_le =+ forAll twoElems $ \(x, y) ->+ (x <. y) == (x <=. y && not (x ==. y))++ gt_ge =+ forAll twoElems $ \(x, y) ->+ (x >. y) == (x >=. y && not (x ==. y))++ ge_le =+ forAll twoElems $ \(x, y) ->+ (x >=. y) == (y <=. x)++ lt_gt =+ forAll twoElems $ \(x, y) ->+ (x <. y) == (y >. x)++-- | Tests relating various total order operators and functions. Does+-- not include any tests from 'isTotalOrder'.++isTotalOrderOperators+ :: Show a+ => Gen a+ -- ^ Generator for arbitrary element.+ -> (a -> Gen a)+ -- ^ Generator for element greater than or equal to argument.+ -> (a -> a -> Bool)+ -- ^ Equal.+ -> (a -> a -> Bool)+ -- ^ Less than or equal.+ -> (a -> a -> Bool)+ -- ^ Less than.+ -> (a -> a -> Bool)+ -- ^ Greater than or equal.+ -> (a -> a -> Bool)+ -- ^ Greater than.+ -> (a -> a -> Ordering)+ -- ^ Compare.+ -> (a -> a -> a)+ -- ^ Minimum.+ -> (a -> a -> a)+ -- ^ Maximum.+ -> [Property]+isTotalOrderOperators element greaterThan+ (==.) (<=.) (<.) (>=.) (>.) cmp mn mx =+ isPartialOrderOperators element greaterThan (==.) (<=.) (<.) (>=.) (>.)+ ++ [compare_lt_eq_gt, compare_max, compare_min]+ where+ twoElems = pair3 element greaterThan++ compare_lt_eq_gt =+ forAll twoElems $ \(x, y) ->+ case cmp x y of+ LT -> x <. y+ EQ -> x ==. y+ GT -> x >. y++ compare_max =+ forAll twoElems $ \(x, y) ->+ case cmp x y of+ LT -> x `mx` y ==. y+ GT -> x `mx` y ==. x+ EQ -> elemBy (==.) (x `mx` y) [x, y]++ compare_min =+ forAll twoElems $ \(x, y) ->+ case cmp x y of+ LT -> x `mn` y ==. x+ GT -> x `mn` y ==. y+ EQ -> elemBy (==.) (x `mn` y) [x, y]++ elemBy op x xs = any (`op` x) xs++-- | Tests that an 'Ord' instance should satisfy to be a total order.++ordIsTotalOrder+ :: (Show a, Ord a)+ => Gen a+ -- ^ Generator for arbitrary element.+ -> (a -> Gen a)+ -- ^ Generator for element equal to argument.+ -> (a -> Gen a)+ -- ^ Generator for element different from argument.+ -> (a -> Gen a)+ -- ^ Generator for element greater than or equal to argument.+ -> [Property]+ordIsTotalOrder element equalTo differentFrom greaterThan =+ isTotalOrderOperators element greaterThan+ (==) (<=) (<) (>=) (>) compare min max+ ++ isTotalOrder element equalTo differentFrom greaterThan (==) (<=)++------------------------------------------------------------------------+-- Helper functions++-- | Given two generators, generates a pair where the second component+-- depends on the first.++pair :: Gen a -> (a -> Gen b) -> Gen (a, b)+pair gen1 gen2 = do+ x <- gen1+ y <- gen2 x+ return (x, y)++-- | 'triple' works like 'pair', but for triples.++triple :: Gen a -> (a -> Gen b) -> (b -> Gen c) -> Gen (a, b, c)+triple gen1 gen2 gen3 = do+ x <- gen1+ y <- gen2 x+ z <- gen3 y+ return (x, y, z)++-- | Given two generators, where the second one depends on elements+-- generated by the first one, 'pair3' generates three kinds of pairs:+--+-- 1. Containing two elements from the first generator.+--+-- 2. Containing one element from the first and one from the second.+--+-- 3. Containing one element from the second and one from the first.++pair3 :: Gen a -> (a -> Gen a) -> Gen (a, a)+pair3 gen1 gen2 =+ oneof [ liftM2 (,) gen1 gen1+ , pair gen1 gen2+ , fmap (snd &&& fst) $ pair gen1 gen2+ ]
+ Test/ChasingBottoms/TestUtilities/Generators.hs view
@@ -0,0 +1,386 @@+{-# OPTIONS -fglasgow-exts #-}++-- | Generators that are part of the testing framework.++-- This module contains _many_ generators. Maybe they should be+-- exported, not just from this module, but from the library as well.++module Test.ChasingBottoms.TestUtilities.Generators+ ( -- * Basic types and functions+ Cogen+ , function+ , NotEqualGen+ , GreaterEqualGen+ , JoinableGen+ -- ** @Bool@ generators+ , bool+ , coBool+ , neBool+ , geBool+ , joinBool+ -- ** @Integer@ generators+ , integer+ , coInteger+ , neInteger+ , geInteger+ , joinInteger+ -- ** @[]@ generators+ , finiteListOf+ , infiniteListOf+ , coListOf+ , neListOf+ , geListOf+ , joinListOf+ -- ** @Tree@ generators+ , Tree(..)+ , finiteTreeOf+ , infiniteTreeOf+ , coTreeOf+ , neTreeOf+ , geTreeOf+ , joinTreeOf+ -- * Tests of the generators+ , tests+ ) where++import Test.ChasingBottoms.IsBottom+import Test.ChasingBottoms.SemanticOrd+import Test.ChasingBottoms.TestUtilities+import Test.QuickCheck+import Test.QuickCheck.Batch (run)+import Data.Generics+import Control.Monad+import Data.Maybe++import Test.ChasingBottoms.ApproxShow+import Test.ChasingBottoms.Nat++------------------------------------------------------------------------+-- Data types++-- | Binary trees with information in the leaves.++data Tree a+ = Branch (Tree a) (Tree a)+ | Leaf a+ deriving (Show, Typeable, Data)++------------------------------------------------------------------------+-- Basic generators++integer :: Gen Integer+integer = frequency [ (1, return bottom), (10, arbitrary) ]++bool :: Gen Bool+bool = elements [bottom, False, True]++finiteListOf :: Gen a -> Gen [a]+finiteListOf gen = sized finList+ where+ finList size | size == 0 = baseCase+ | otherwise =+ frequency [ (1, baseCase)+ , (10, do elem <- gen+ l <- finList (size - 1)+ return (elem : l)+ )+ ]++ baseCase = elements [bottom, []]++finiteTreeOf :: Gen a -> Gen (Tree a)+finiteTreeOf gen = sized finTree+ where+ finTree size | size == 0 = baseCase+ | otherwise =+ frequency [ (1, baseCase)+ , (2, do left <- finTree (size `div` 2)+ right <- finTree (size `div` 2)+ return (Branch left right)+ )+ ]++ baseCase = frequency [(1, bottom), (3, liftM Leaf gen)]++-- | Definitely infinite lists.++infiniteListOf :: Gen a -> Gen [a]+infiniteListOf gen = liftM2 (:) gen (infiniteListOf gen)++-- | Possibly infinite trees.++infiniteTreeOf :: Gen a -> Gen (Tree a)+infiniteTreeOf gen = infTree+ where+ infTree = frequency [ (1, return bottom)+ , (1, liftM Leaf gen)+ , (3, liftM2 Branch infTree infTree)+ ]++testGen :: (Show a, Data a) => Nat -> Gen a -> IO ()+testGen depth gen = test $ forAll gen $ \n ->+ collect (approxShow depth n) $ True++------------------------------------------------------------------------+-- Cogenerators++-- | A mapping from an argument to a generator transformer, like the+-- 'coarbitrary' function.+--+-- Note that the functions generated by the cogenerators in this+-- module are not necessarily monotone.++type Cogen a = forall b. a -> Gen b -> Gen b++coBool :: Cogen Bool+coBool b | isBottom b = variant 0+coBool False = variant 1+coBool True = variant 2++coInteger :: Cogen Integer+coInteger i | isBottom i = variant 0+ | otherwise = variant 1 . coarbitrary i++coListOf :: Cogen a -> Cogen [a]+coListOf cog xs | isBottom xs = variant 0+coListOf cog [] = variant 1+coListOf cog (x:xs) = variant 2 . cog x . coListOf cog xs++coTreeOf :: Cogen a -> Cogen (Tree a)+coTreeOf cog xs | isBottom xs = variant 0+coTreeOf cog (Leaf x) = variant 1 . cog x+coTreeOf cog (Branch l r) = variant 2 . coTreeOf cog l . coTreeOf cog r++-- | Given a 'Cogen' and a 'Gen', generate a function.++-- Note that the functions generated by 'promote' below are all+-- non-bottom.++function :: Cogen a -> Gen b -> Gen (a -> b)+function coGen gen = frequency [ (1, return bottom)+ , (50, promote (\a -> coGen a gen))+ ]++testFunction :: (Data a, Data b) => Nat -> Cogen a -> Gen b -> [a] -> IO ()+testFunction depth coGen gen inputs =+ test $ forAll (function coGen gen) $ \f ->+ collect (map (\x -> approxShow depth (x, f x)) inputs) $ True++------------------------------------------------------------------------+-- Generators for element not equal to argument++-- | Mapping from argument to generator of elements not equal to+-- argument.++type NotEqualGen a = a -> Gen a++neBool :: NotEqualGen Bool+neBool b | isBottom b = elements [False, True]+neBool False = elements [bottom, True]+neBool True = elements [bottom, False]++neInteger :: NotEqualGen Integer+neInteger i | isBottom i = arbitrary+ | otherwise =+ frequency [ (1, return bottom)+ , (10, do j <- arbitrary+ let j' = if j >= 0 then j + 1 else j - 1+ return (i + j')+ )+ ]++neListOf :: Gen a -> NotEqualGen a -> (Gen a -> Gen [a]) -> NotEqualGen [a]+neListOf gen neg listOf xs = neList xs+ where+ neList xs+ | isBottom xs = frequency [ (1, return []), (10, nonEmpty gen) ]+ | otherwise = case xs of+ [] -> frequency [ (1, return bottom), (10, nonEmpty gen) ]+ (y:ys) -> frequency [ (1, return bottom)+ , (1, return [])+ , (5, nonEmpty (neg y))+ , (5, do y' <- neg y+ return (y':ys)+ )+ , (5, do ys' <- neList ys+ return (y:ys')+ )+ ]++ nonEmpty headGen = do x <- headGen+ xs <- listOf gen+ return (x:xs)++neTreeOf :: Gen a+ -> NotEqualGen a+ -> (Gen a -> Gen (Tree a))+ -> NotEqualGen (Tree a)+neTreeOf gen neg treeOf t = neTree t+ where+ neTree t+ | isBottom t = frequency [ (1, leaf gen), (10, node) ]+ | otherwise = case t of+ Leaf x -> frequency [ (1, smallTreeNE x), (2, node) ]+ Branch l r -> frequency [ (1, return bottom)+ , (2, leaf gen)+ , (2, do l' <- neTree l+ return (Branch l' r)+ )+ , (2, do r' <- neTree r+ return (Branch l r')+ )+ , (2, do l' <- neTree l+ r' <- node+ return (Branch l' r')+ )+ , (2, do l' <- node+ r' <- neTree r+ return (Branch l' r')+ )+ ]++ leaf g = liftM Leaf g+ smallTreeNE x = frequency [(1, return bottom), (3, leaf (neg x))]++ node = do l <- treeOf gen+ r <- treeOf gen+ return (Branch l r)++prop_notEqualGen element gen =+ forAll (pair element gen) $ \(x, y) ->+ x /=! y++testGenPair :: (Show a, Data a) => Nat -> Gen a -> (a -> Gen a) -> IO ()+testGenPair depth gen gen' = test $+ forAll (pair gen gen') $ \(x, y) ->+ collect (approxShow depth (x, y)) $ True++------------------------------------------------------------------------+-- Generators for element greater than or equal to argument++-- | Mapping from argument to generator of elements greater than or+-- equal to argument.++type GreaterEqualGen a = a -> Gen a++-- | 'GreaterEqualGen' for flat CPOs.++flatGEGen :: Gen a -> GreaterEqualGen a+flatGEGen gen x | isBottom x = gen+ | otherwise = return x++geBool :: GreaterEqualGen Bool+geBool = flatGEGen bool++geInteger :: GreaterEqualGen Integer+geInteger = flatGEGen integer++geListOf :: Gen a+ -> GreaterEqualGen a+ -> (Gen a -> Gen [a])+ -> GreaterEqualGen [a]+geListOf gen geGen listOf xs+ | isBottom xs = listOf gen+ | otherwise = case xs of+ [] -> return []+ y:ys -> do y' <- geGen y+ ys' <- geListOf gen geGen listOf ys+ return (y':ys')++geTreeOf :: Gen a+ -> GreaterEqualGen a+ -> (Gen a -> Gen (Tree a))+ -> GreaterEqualGen (Tree a)+geTreeOf gen geGen treeOf t+ | isBottom t = treeOf gen+ | otherwise = case t of+ Leaf x -> liftM Leaf (geGen x)+ Branch l r -> do l' <- geTreeOf gen geGen treeOf l+ r' <- geTreeOf gen geGen treeOf r+ return (Branch l' r')++prop_greaterEqualGen element gen =+ forAll (pair element gen) $ \(x, y) ->+ x <=! y++------------------------------------------------------------------------+-- Generators for pairs whose components' join exists++-- | Mapping from argument to generator of elements whose join with+-- the argument is likely to exist.+--+-- Note that the meet of these elements is also likely to be+-- \"interesting\".++type JoinableGen a = a -> Gen a++-- | 'JoinableGen' for flat CPOs.++flatJoinGen :: Gen a -> JoinableGen a+flatJoinGen gen x | isBottom x = gen+ | otherwise = frequency [(1, return bottom), (4, return x)]++joinBool :: JoinableGen Bool+joinBool = flatJoinGen bool++joinInteger :: JoinableGen Integer+joinInteger = flatJoinGen integer++joinListOf :: Gen a -> JoinableGen a -> (Gen a -> Gen [a]) -> JoinableGen [a]+joinListOf gen joinGen listOf xs+ | isBottom xs = listOf gen+ | otherwise = case xs of+ [] -> frequency [(1, return bottom), (4, return [])]+ y:ys -> frequency [ (1, return bottom)+ , (10, do y' <- joinGen y+ ys' <- joinListOf gen joinGen listOf ys+ return (y':ys')+ )+ ]++joinTreeOf :: Gen a+ -> JoinableGen a+ -> (Gen a -> Gen (Tree a))+ -> JoinableGen (Tree a)+joinTreeOf gen joinGen treeOf t+ | isBottom t = treeOf gen+ | otherwise = case t of+ Leaf x -> frequency [(1, return bottom), (4, liftM Leaf (joinGen x))]+ Branch l r -> frequency [ (1, return bottom)+ , (5, do l' <- joinTreeOf gen joinGen treeOf l+ r' <- joinTreeOf gen joinGen treeOf r+ return (Branch l' r')+ )+ ]++prop_joinableGen element gen =+ forAll (pair element gen) $ \(x, y) ->+ isJust (x \/! y)++------------------------------------------------------------------------++-- | All tests collected together.++tests :: IO Bool+tests = runQuickCheckTests $ map run theTests+ where+ theTests =+ [ prop_notEqualGen bool neBool+ , prop_notEqualGen integer neInteger+ , prop_notEqualGen (finiteListOf bool)+ (neListOf bool neBool finiteListOf)+ , prop_notEqualGen (finiteTreeOf integer)+ (neTreeOf integer neInteger finiteTreeOf)+ , prop_greaterEqualGen bool geBool+ , prop_greaterEqualGen integer geInteger+ , prop_greaterEqualGen (finiteListOf bool)+ (geListOf bool geBool finiteListOf)+ , prop_greaterEqualGen (finiteTreeOf integer)+ (geTreeOf integer geInteger finiteTreeOf)+ , prop_joinableGen bool joinBool+ , prop_joinableGen integer joinInteger+ , prop_joinableGen (finiteListOf bool)+ (joinListOf bool joinBool finiteListOf)+ , prop_joinableGen (finiteTreeOf integer)+ (joinTreeOf integer joinInteger finiteTreeOf)+ ]
+ Test/ChasingBottoms/Tests.hs view
@@ -0,0 +1,75 @@+{-# OPTIONS -fglasgow-exts #-}++-- | Tests of almost everything related to "Test.ChasingBottoms".++module Test.ChasingBottoms.Tests (main) where++import qualified Test.ChasingBottoms.Approx.Tests as Approx+import qualified Test.ChasingBottoms.ApproxShow.Tests as ApproxShow+import qualified Test.ChasingBottoms.ContinuousFunctions.Tests as ContinuousFunctions+import qualified Test.ChasingBottoms.IsBottom.Tests as IsBottom+import qualified Test.ChasingBottoms.IsType.Tests as IsType+import qualified Test.ChasingBottoms.Nat.Tests as Nat+import qualified Test.ChasingBottoms.SemanticOrd.Tests as SemanticOrd+import qualified Test.ChasingBottoms.TestUtilities.Generators as Generators+import qualified Test.ChasingBottoms.TimeOut.Tests as TimeOut+import System.Exit++-- | A class for things that can be tested.+class Test a where+ test :: String -- ^ Description of test.+ -> a -- ^ Test.+ -> IO Bool -- ^ True if the test succeeded.++-- | @'indent' a@ shows @a@ and indents the output by two spaces. A+-- trailing newline is added if necessary.++-- This function could be more efficient.++indent :: (Show a) => a -> IO ()+indent a = putStr . maybeNL . unlines . map (" " ++) . lines $ show a+ where maybeNL s | null s = "\n"+ | last s == '\n' = s+ | otherwise = s ++ "\n"++instance Test Bool where+ test desc b = do+ putStrLn desc+ indent b+ return b++instance Test [Bool] where+ test desc bs = do+ putStrLn desc+ indent bs+ return $ and bs++instance Test (IO Bool) where+ test desc io = do+ putStrLn desc+ b <- io+ indent b+ return b++-- | This function runs all the tests, and prints out a message+-- indicating whether any failures were encountered.++main :: IO ()+main = do+ ok <- fmap and $ sequence theTests+ putStrLn ""+ if ok then+ putStrLn "All tests succeeded."+ else do+ putStrLn "At least one test failed."+ exitFailure+ where theTests = [ test "Approx:" Approx.tests+ , test "ApproxShow:" ApproxShow.tests+ , test "ContinuousFunctions:" ContinuousFunctions.tests+ , test "Generators:" Generators.tests+ , test "IsBottom:" IsBottom.tests+ , test "IsType:" IsType.tests+ , test "Nat:" Nat.tests+ , test "SemanticOrd:" SemanticOrd.tests+ , test "TimeOut:" TimeOut.tests+ ]
+ Test/ChasingBottoms/TimeOut.hs view
@@ -0,0 +1,130 @@+{-# OPTIONS -fglasgow-exts #-}++-- |+-- Module : Test.ChasingBottoms.TimeOut+-- Copyright : (c) Nils Anders Danielsson 2004-2007+-- License : See the file LICENCE.+-- +-- Maintainer : http://www.cs.chalmers.se/~nad/+-- Stability : experimental+-- Portability : non-portable (preemptive scheduling)+--+-- When dealing with \"hard bottoms\", i.e. non-terminating+-- computations that do not result in exceptions, the following functions+-- may be handy.+--+-- Note that a computation is considered to have terminated when it+-- has reached weak head normal form (i.e. something distinct from+-- bottom).++module Test.ChasingBottoms.TimeOut+ ( Result(..)+ , timeOut+ , timeOut'+ , timeOutMicro+ , timeOutMicro'+ ) where++import Control.Concurrent+import Data.Dynamic+import qualified Control.Exception as E++data Result a+ = Value a+ | NonTermination+ | Exception E.Exception+ deriving (Eq, Show, Typeable)++-- | @'timeOut' n c@ runs @c@ for at most @n@ seconds (modulo+-- scheduling issues).+--+-- * If the computation terminates before that, then+-- @'Value' v@ is returned, where @v@ is the resulting value. Note+-- that this value may be equal to bottom, e.g. if @c = 'return'+-- 'Test.ChasingBottoms.IsBottom.bottom'@.+--+-- * If the computation does not terminate, then 'NonTermination' is+-- returned.+--+-- * If the computation raises an exception, then @'Exception' e@ is+-- returned, where @e@ is the exception.++timeOut :: Int -> IO a -> IO (Result a)+timeOut = timeOutMicro . (* 10^6)++-- | 'timeOutMicro' takes a delay in microseconds. Note that the+-- resolution is not necessarily very high (the last time I checked it+-- was 0.02 seconds when using the standard runtime system settings+-- for GHC).++timeOutMicro :: Int -> IO a -> IO (Result a)+timeOutMicro delay io = do+ mv <- newEmptyMVar+ let putException = putMVar mv . Exception+ ioThread <- forkIO $ (io >>= putMVar mv . Value)+ `E.catch` (\e -> case e of+ E.DynException d -> case fromDynamic d of+ Just Die -> return () -- Thread properly killed.+ Nothing -> putException e+ _ -> putException e)+ reaper <- forkIO $ do+ threadDelay delay+ putMVar mv NonTermination+ result <- takeMVar mv+ killThread' ioThread+ killThread reaper+ return result++-- Since 'ioThread' above should return exceptions raised in the code+-- we cannot kill the thread using killThread, which raises+-- @'AsyncException' 'ThreadKilled'@. We use the locally defined type+-- 'Die' together with a dynamic exception instead.++data Die = Die deriving Typeable++killThread' threadId = E.throwDynTo threadId Die++-- | 'timeOut'' is a variant which can be used for pure+-- computations. The definition,+--+-- @+-- 'timeOut'' n = 'timeOut' n . 'E.evaluate'+-- @+--+-- ensures that @'timeOut'' 1 'Test.ChasingBottoms.IsBottom.bottom'@+-- usually returns @'Exception' \<something\>@. (@'timeOut' 1 ('return'+-- 'Test.ChasingBottoms.IsBottom.bottom')@ usually returns @'Value'+-- 'Test.ChasingBottoms.IsBottom.bottom'@; in other words, the+-- computation reaches whnf almost immediately, defeating the purpose+-- of the time-out.)++timeOut' :: Int -> a -> IO (Result a)+timeOut' n = timeOut n . E.evaluate++-- | 'timeOutMicro'' is the equivalent variant of 'timeOutMicro':+--+-- @+-- 'timeOutMicro'' n = 'timeOutMicro' n . 'E.evaluate'+-- @++timeOutMicro' :: Int -> a -> IO (Result a)+timeOutMicro' n = timeOutMicro n . E.evaluate++------------------------------------------------------------------------++-- There shouldn't be any memory leaks in the code above. Profiling+-- the code below also seems to suggest that there aren't any+-- problems. However, GHCi (with :set +r) eats up more and more memory+-- if the computation below is rerun a couple of times. Hmm, that+-- seems to be the case also when running simply (reverse [1..]). It+-- probably means that GHCi never releases any memory.++main = do+ let n = 1; d = 000000+ {-# SCC "a" #-} timeOut' n (reverse [1..]) >>= print+ threadDelay d+ {-# SCC "b" #-} timeOut' n (reverse [1..]) >>= print+ threadDelay d+ {-# SCC "c" #-} timeOut' n (reverse [1..]) >>= print+ threadDelay d+ {-# SCC "d" #-} timeOut' n (reverse [1..]) >>= print
+ Test/ChasingBottoms/TimeOut/Tests.hs view
@@ -0,0 +1,31 @@+-- | Tests of the functions in "Test.ChasingBottoms.TimeOut".++module Test.ChasingBottoms.TimeOut.Tests (tests) where++-- The "Micro" variants are not tested directly, but they are used+-- internally by the functions below.++import Test.ChasingBottoms.TimeOut+import Test.ChasingBottoms.Approx+import Test.ChasingBottoms.IsBottom+import Test.ChasingBottoms.SemanticOrd++tests :: IO Bool+tests = do+ r1 <- timeOut n bottom+ r1b <- timeOut n $ return bottom+ r2 <- timeOut' n bottom+ r3 <- timeOut n $ return list+ r4 <- timeOut' n list+ r5 <- timeOut n $ return $ reverse list+ r6 <- timeOut' n $ reverse list+ let result = case (r1, r1b, r2, r3, r4, r5, r6) of+ ( Exception _, Value b, Exception _, Value xs, Value ys+ , Value _nt, NonTermination)+ -> isBottom b && xs =~= list && ys =~= list+ _ -> False+ return result+ where n = 1+ list = [1..] :: [Integer]+ xs =~= ys = appr xs ==! appr ys+ appr = approxAll 20
+ docs/Test-ChasingBottoms-Approx.html view
@@ -0,0 +1,339 @@+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">+<!--Rendered using the Haskell Html Library v0.2-->+<HTML+><HEAD+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"+><TITLE+>Test.ChasingBottoms.Approx</TITLE+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"+><SCRIPT SRC="haddock.js" TYPE="text/javascript"+></SCRIPT+></HEAD+><BODY+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="topbar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "+></TD+><TD CLASS="title"+>Chasing Bottoms</TD+><TD CLASS="topbut"+><A HREF="index.html"+>Contents</A+></TD+><TD CLASS="topbut"+><A HREF="doc-index.html"+>Index</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="modulebar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><FONT SIZE="6"+>Test.ChasingBottoms.Approx</FONT+></TD+><TD ALIGN="right"+><TABLE CLASS="narrow" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="infohead"+>Portability</TD+><TD CLASS="infoval"+>non-portable (GHC-specific)</TD+></TR+><TR+><TD CLASS="infohead"+>Stability</TD+><TD CLASS="infoval"+>experimental</TD+></TR+><TR+><TD CLASS="infohead"+>Maintainer</TD+><TD CLASS="infoval"+>http://www.cs.chalmers.se/~nad/</TD+></TR+></TABLE+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+></TABLE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="section1"+>Description</TD+></TR+><TR+><TD CLASS="doc"+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="section1"+>Synopsis</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="body"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="decl"+><SPAN CLASS="keyword"+>class</SPAN+> <A HREF="#t%3AApprox"+>Approx</A+> a <SPAN CLASS="keyword"+>where</SPAN+></TD+></TR+><TR+><TD CLASS="body"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="decl"+><A HREF="#v%3AapproxAll"+>approxAll</A+> :: <A HREF="Test-ChasingBottoms-Nat.html#t%3ANat"+>Nat</A+> -> a -> a</TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3Aapprox"+>approx</A+> :: <A HREF="Test-ChasingBottoms-Nat.html#t%3ANat"+>Nat</A+> -> a -> a</TD+></TR+></TABLE+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="section1"+>Documentation</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><SPAN CLASS="keyword"+>class</SPAN+> <A NAME="t%3AApprox"+></A+><B+>Approx</B+> a <SPAN CLASS="keyword"+>where</SPAN+></TD+></TR+><TR+><TD CLASS="body"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="ndoc"+><P+><TT+><A HREF="Test-ChasingBottoms-Approx.html#t%3AApprox"+>Approx</A+></TT+> is a class for approximation functions as described+in The generic approximation lemma, Graham Hutton and Jeremy+Gibbons, Information Processing Letters, 79(4):197-201, Elsevier+Science, August 2001, <A HREF="http://www.cs.nott.ac.uk/~gmh/bib.html"+>http://www.cs.nott.ac.uk/~gmh/bib.html</A+>.+</P+><P+>Instances are provided for all members of the <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Generics-Basics.html#t%3AData"+>Data</A+></TT+> type class. Due+to the limitations of the <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Generics.html"+>Data.Generics</A+> approach to generic+programming, which is not really aimed at this kind of application,+the implementation is only guaranteed to perform correctly, with+respect to the paper (and modulo any bugs), on non-mutually-recursive+sum-of-products datatypes. In particular, nested and mutually+recursive types are not handled correctly with respect to the+paper. The specification below is correct, though (if we assume that+the <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Generics-Basics.html#t%3AData"+>Data</A+></TT+> instances are well-behaved).+</P+><P+>In practice the <TT+><A HREF="Test-ChasingBottoms-Approx.html#v%3AapproxAll"+>approxAll</A+></TT+> function can probably be more useful than+<TT+><A HREF="Test-ChasingBottoms-Approx.html#v%3Aapprox"+>approx</A+></TT+>. It traverses down <EM+>all</EM+> subterms, and it should be possible+to prove a variant of the approximation lemma which <TT+><A HREF="Test-ChasingBottoms-Approx.html#v%3AapproxAll"+>approxAll</A+></TT+>+satisfies.+</P+></TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="section4"+>Methods</TD+></TR+><TR+><TD CLASS="body"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="decl"+><A NAME="v%3AapproxAll"+></A+><B+>approxAll</B+> :: <A HREF="Test-ChasingBottoms-Nat.html#t%3ANat"+>Nat</A+> -> a -> a</TD+></TR+><TR+><TD CLASS="doc"+><TT+><TT+><A HREF="Test-ChasingBottoms-Approx.html#v%3AapproxAll"+>approxAll</A+></TT+> n x</TT+> traverses <TT+>n</TT+> levels down in <TT+>x</TT+> and replaces all+ values at that level with bottoms.+</TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3Aapprox"+></A+><B+>approx</B+> :: <A HREF="Test-ChasingBottoms-Nat.html#t%3ANat"+>Nat</A+> -> a -> a</TD+></TR+><TR+><TD CLASS="doc"+><TT+><A HREF="Test-ChasingBottoms-Approx.html#v%3Aapprox"+>approx</A+></TT+> works like <TT+><A HREF="Test-ChasingBottoms-Approx.html#v%3AapproxAll"+>approxAll</A+></TT+>, but the traversal and+ replacement is only performed at subterms of the same monomorphic+ type as the original term. For polynomial datatypes this is+ exactly what the version of <TT+>approx</TT+> described in the paper above+ does.+</TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="section4"+><IMG SRC="minus.gif" CLASS="coll" ONCLICK="toggle(this,'i:Approx')" ALT="show/hide"+> Instances</TD+></TR+><TR+><TD CLASS="body"+><DIV ID="i:Approx" STYLE="display:block;"+><TABLE CLASS="vanilla" CELLSPACING="1" CELLPADDING="0"+><TR+><TD CLASS="decl"+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Generics-Basics.html#t%3AData"+>Data</A+> a => <A HREF="Test-ChasingBottoms-Approx.html#t%3AApprox"+>Approx</A+> a</TD+></TR+></TABLE+></DIV+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="botbar"+>Produced by <A HREF="http://www.haskell.org/haddock/"+>Haddock</A+> version 0.7</TD+></TR+></TABLE+></BODY+></HTML+>
+ docs/Test-ChasingBottoms-ApproxShow.html view
@@ -0,0 +1,369 @@+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">+<!--Rendered using the Haskell Html Library v0.2-->+<HTML+><HEAD+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"+><TITLE+>Test.ChasingBottoms.ApproxShow</TITLE+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"+><SCRIPT SRC="haddock.js" TYPE="text/javascript"+></SCRIPT+></HEAD+><BODY+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="topbar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "+></TD+><TD CLASS="title"+>Chasing Bottoms</TD+><TD CLASS="topbut"+><A HREF="index.html"+>Contents</A+></TD+><TD CLASS="topbut"+><A HREF="doc-index.html"+>Index</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="modulebar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><FONT SIZE="6"+>Test.ChasingBottoms.ApproxShow</FONT+></TD+><TD ALIGN="right"+><TABLE CLASS="narrow" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="infohead"+>Portability</TD+><TD CLASS="infoval"+>non-portable (GHC-specific)</TD+></TR+><TR+><TD CLASS="infohead"+>Stability</TD+><TD CLASS="infoval"+>experimental</TD+></TR+><TR+><TD CLASS="infohead"+>Maintainer</TD+><TD CLASS="infoval"+>http://www.cs.chalmers.se/~nad/</TD+></TR+></TABLE+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+></TABLE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="section1"+>Description</TD+></TR+><TR+><TD CLASS="doc"+>Functions for converting arbitrary (non-function, partial,+ possibly infinite) values into strings.+</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="section1"+>Synopsis</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="body"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="decl"+><SPAN CLASS="keyword"+>type</SPAN+> <A HREF="#t%3APrec"+>Prec</A+> = <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Int.html#t%3AInt"+>Int</A+></TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><SPAN CLASS="keyword"+>class</SPAN+> <A HREF="#t%3AApproxShow"+>ApproxShow</A+> a <SPAN CLASS="keyword"+>where</SPAN+></TD+></TR+><TR+><TD CLASS="body"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="decl"+><A HREF="#v%3AapproxShowsPrec"+>approxShowsPrec</A+> :: <A HREF="Test-ChasingBottoms-Nat.html#t%3ANat"+>Nat</A+> -> <A HREF="Test-ChasingBottoms-ApproxShow.html#t%3APrec"+>Prec</A+> -> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Text-Show.html#t%3AShowS"+>ShowS</A+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3AapproxShows"+>approxShows</A+> :: <A HREF="Test-ChasingBottoms-Nat.html#t%3ANat"+>Nat</A+> -> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Text-Show.html#t%3AShowS"+>ShowS</A+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3AapproxShow"+>approxShow</A+> :: <A HREF="Test-ChasingBottoms-Nat.html#t%3ANat"+>Nat</A+> -> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Char.html#t%3AString"+>String</A+></TD+></TR+></TABLE+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="section1"+>Documentation</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><SPAN CLASS="keyword"+>type</SPAN+> <A NAME="t%3APrec"+></A+><B+>Prec</B+> = <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Int.html#t%3AInt"+>Int</A+></TD+></TR+><TR+><TD CLASS="doc"+>Precedence level.+</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><SPAN CLASS="keyword"+>class</SPAN+> <A NAME="t%3AApproxShow"+></A+><B+>ApproxShow</B+> a <SPAN CLASS="keyword"+>where</SPAN+></TD+></TR+><TR+><TD CLASS="body"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="section4"+>Methods</TD+></TR+><TR+><TD CLASS="body"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="decl"+><A NAME="v%3AapproxShowsPrec"+></A+><B+>approxShowsPrec</B+> :: <A HREF="Test-ChasingBottoms-Nat.html#t%3ANat"+>Nat</A+> -> <A HREF="Test-ChasingBottoms-ApproxShow.html#t%3APrec"+>Prec</A+> -> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Text-Show.html#t%3AShowS"+>ShowS</A+></TD+></TR+><TR+><TD CLASS="doc"+><P+>The <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Generics-Basics.html#t%3AData"+>Data</A+></TT+> instance of <TT+><A HREF="Test-ChasingBottoms-ApproxShow.html#t%3AApproxShow"+>ApproxShow</A+></TT+> makes sure that+ <TT+><TT+><A HREF="Test-ChasingBottoms-ApproxShow.html#v%3AapproxShowsPrec"+>approxShowsPrec</A+></TT+> n</TT+> behaves (more or less) like the derived+ version of <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Text-Show.html#v%3AshowsPrec"+>showsPrec</A+></TT+>, with the following differences:+</P+><UL+><LI+> After <TT+>n</TT+> levels of descent into a term the output is+ replaced by <TT+>"_"</TT+>.+</LI+><LI+> All detectable occurences of bottoms are replaced by <TT+>"_|_"</TT+>.+</LI+><LI+> Non-bottom functions are displayed as <TT+>"<function /= _|_>"</TT+>.+</LI+></UL+></TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3AapproxShows"+></A+><B+>approxShows</B+> :: <A HREF="Test-ChasingBottoms-Nat.html#t%3ANat"+>Nat</A+> -> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Text-Show.html#t%3AShowS"+>ShowS</A+></TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3AapproxShow"+></A+><B+>approxShow</B+> :: <A HREF="Test-ChasingBottoms-Nat.html#t%3ANat"+>Nat</A+> -> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Char.html#t%3AString"+>String</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="section4"+><IMG SRC="minus.gif" CLASS="coll" ONCLICK="toggle(this,'i:ApproxShow')" ALT="show/hide"+> Instances</TD+></TR+><TR+><TD CLASS="body"+><DIV ID="i:ApproxShow" STYLE="display:block;"+><TABLE CLASS="vanilla" CELLSPACING="1" CELLPADDING="0"+><TR+><TD CLASS="decl"+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Generics-Basics.html#t%3AData"+>Data</A+> a => <A HREF="Test-ChasingBottoms-ApproxShow.html#t%3AApproxShow"+>ApproxShow</A+> a</TD+></TR+></TABLE+></DIV+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="botbar"+>Produced by <A HREF="http://www.haskell.org/haddock/"+>Haddock</A+> version 0.7</TD+></TR+></TABLE+></BODY+></HTML+>
+ docs/Test-ChasingBottoms-ContinuousFunctions.html view
@@ -0,0 +1,1390 @@+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">+<!--Rendered using the Haskell Html Library v0.2-->+<HTML+><HEAD+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"+><TITLE+>Test.ChasingBottoms.ContinuousFunctions</TITLE+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"+><SCRIPT SRC="haddock.js" TYPE="text/javascript"+></SCRIPT+></HEAD+><BODY+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="topbar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "+></TD+><TD CLASS="title"+>Chasing Bottoms</TD+><TD CLASS="topbut"+><A HREF="index.html"+>Contents</A+></TD+><TD CLASS="topbut"+><A HREF="doc-index.html"+>Index</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="modulebar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><FONT SIZE="6"+>Test.ChasingBottoms.ContinuousFunctions</FONT+></TD+><TD ALIGN="right"+><TABLE CLASS="narrow" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="infohead"+>Portability</TD+><TD CLASS="infoval"+>non-portable (GHC-specific)</TD+></TR+><TR+><TD CLASS="infohead"+>Stability</TD+><TD CLASS="infoval"+>experimental</TD+></TR+><TR+><TD CLASS="infohead"+>Maintainer</TD+><TD CLASS="infoval"+>http://www.cs.chalmers.se/~nad/</TD+></TR+></TABLE+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="section4"+><B+>Contents</B+></TD+></TR+><TR+><TD+><DL+><DT+><A HREF="#1"+>Basic framework+</A+></DT+><DT+><A HREF="#2"+>Liftings of some QuickCheck functionality+</A+></DT+><DT+><A HREF="#3"+>Generic <TT+>MakePM</TT+>+</A+></DT+><DT+><A HREF="#4"+>Some <TT+>MakeResult</TT+>s+</A+></DT+></DL+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="section1"+>Description</TD+></TR+><TR+><TD CLASS="doc"+><P+>Note: <EM+>This module is unfinished and experimental. However, I do+ not think that I will ever finish it, so I have released it in its+ current state. The documentation below may not be completely+ correct. The source code lists some things which should be+ addressed.</EM+>+</P+><P+>A framework for generating possibly non-strict, partial,+ continuous functions.+</P+><P+>The functions generated using the standard QuickCheck <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/QuickCheck-1.1.0.0/Test-QuickCheck.html#t%3AArbitrary"+>Arbitrary</A+></TT+>+ instances are all strict. In the presence of partial and infinite+ values testing using only strict functions leads to worse coverage+ than if more general functions are used, though.+</P+><P+>Using <TT+><A HREF="Test-ChasingBottoms-IsBottom.html#v%3AisBottom"+>isBottom</A+></TT+> it is relatively easy to generate possibly+ non-strict functions that are, in general, not monotone. For+ instance, using+</P+><PRE+> type Cogen a = forall b. a -> Gen b -> Gen b+ + integer :: Gen Integer+ integer = frequency [ (1, return bottom), (10, arbitrary) ]+ + coBool :: CoGen Bool+ coBool b | isBottom b = variant 0+ coBool False = variant 1+ coBool True = variant 2+ + function :: Cogen a -> Gen b -> Gen (a -> b)+ function coGen gen = promote (\a -> coGen a gen)+</PRE+><P+>we can generate possibly non-strict functions from <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Bool.html#t%3ABool"+>Bool</A+></TT+> to+ <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Prelude.html#t%3AInteger"+>Integer</A+></TT+> using <TT+>function coBool integer</TT+>. There is a high+ likelihood that the functions generated are not monotone, though.+ The reason that we can get non-monotone functions in a language+ like Haskell is that we are using the impure function <TT+><A HREF="Test-ChasingBottoms-IsBottom.html#v%3AisBottom"+>isBottom</A+></TT+>.+</P+><P+>Sometimes using possibly non-monotone functions is good enough,+ since that set of functions is a superset of the continuous+ functions. However, say that we want to test that <TT+>x+ <TT+><A HREF="Test-ChasingBottoms-SemanticOrd.html#v%3A%3C%3D%21"+><=!</A+></TT+> y</TT+> implies that <TT+>f x+ <TT+><A HREF="Test-ChasingBottoms-SemanticOrd.html#v%3A%3C%3D%21"+><=!</A+></TT+> f y</TT+> for all functions <TT+>f</TT+>+ (whenever the latter expression returns a total result). This+ property is not valid in the presence of non-monotone functions.+</P+><P+>By avoiding <TT+><A HREF="Test-ChasingBottoms-IsBottom.html#v%3AisBottom"+>isBottom</A+></TT+> and, unlike the standard <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/QuickCheck-1.1.0.0/Test-QuickCheck.html#v%3Acoarbitrary"+>coarbitrary</A+></TT+>+ functions, deferring some pattern matches, we can generate+ continuous, possibly non-strict functions. There are two steps+ involved in generating a continuous function using the framework+ defined here.+</P+><OL+><LI+> First the argument to the function is turned into a+ <TT+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3APatternMatch"+>PatternMatch</A+></TT+>. A <TT+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3APatternMatch"+>PatternMatch</A+></TT+> wraps up the pattern match on+ the top-level constructor of the argument, plus all further+ pattern matches on the children of the argument. Just like when+ <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/QuickCheck-1.1.0.0/Test-QuickCheck.html#v%3Acoarbitrary"+>coarbitrary</A+></TT+> is used a pattern match is represented as a+ generator transformer. The difference here is that there is not+ just one transformation per input, but one transformation per+ constructor in the input. <TT+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3APatternMatch"+>PatternMatch</A+></TT+>es can be constructed+ generically using <TT+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#v%3Amatch"+>match</A+></TT+>.+</LI+><LI+> Then the result is generated, almost like for a normal+ <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/QuickCheck-1.1.0.0/Test-QuickCheck.html#t%3AArbitrary"+>Arbitrary</A+></TT+> instance. However, for each constructor generated a+ subset of the transformations from step 1 are applied. This+ transformation application is wrapped up in the function+ <TT+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#v%3Atransform"+>transform</A+></TT+>.+</LI+></OL+><P+>The net result of this is that some pattern matches are performed+ later, or not at all, so functions can be lazy.+</P+><P+>Here is an example illustrating typical use of this framework:+</P+><PRE+> data Tree a+ = Branch (Tree a) (Tree a)+ | Leaf a+ deriving (Show, Typeable, Data)+ + finiteTreeOf :: MakeResult a -> MakeResult (Tree a)+ finiteTreeOf makeResult = sized' tree+ where+ tree size = transform $+ if size == 0 then+ baseCase+ else+ frequency' [ (1, baseCase)+ , (1, liftM2 Branch tree' tree')+ ]+ where+ tree' = tree (size `div` 2)+ + baseCase =+ frequency' [ (1, return bottom)+ , (2, liftM Leaf makeResult)+ ]+</PRE+><P+>Note the use of <TT+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#v%3Atransform"+>transform</A+></TT+>. To use this function to generate+ functions of type <TT+>Bool -> Tree Integer</TT+> we can use+</P+><PRE+> forAll (functionTo (finiteTreeOf flat)) $+ \(f :: Bool -> Tree Integer) ->+ ...+</PRE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="section1"+>Synopsis</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="body"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="decl"+><A HREF="#v%3Afunction"+>function</A+> :: <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakePM"+>MakePM</A+> a -> <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> b -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/QuickCheck-1.1.0.0/Test-QuickCheck.html#t%3AGen"+>Gen</A+> (a -> b)</TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3AfunctionTo"+>functionTo</A+> :: <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Generics-Basics.html#t%3AData"+>Data</A+> a => <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> b -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/QuickCheck-1.1.0.0/Test-QuickCheck.html#t%3AGen"+>Gen</A+> (a -> b)</TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><SPAN CLASS="keyword"+>data</SPAN+> <A HREF="#t%3APatternMatch"+>PatternMatch</A+> = <A HREF="#v%3APatternMatch"+>PatternMatch</A+> {<TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="recfield"+><A HREF="#v%3Aapply"+>apply</A+> :: <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AGenTransformer"+>GenTransformer</A+></TD+></TR+><TR+><TD CLASS="recfield"+><A HREF="#v%3Amore"+>more</A+> :: (<A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/containers-0.1.0.0/Data-Sequence.html#t%3ASeq"+>Seq</A+> <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3APatternMatch"+>PatternMatch</A+>)</TD+></TR+></TABLE+>}</TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><SPAN CLASS="keyword"+>type</SPAN+> <A HREF="#t%3AGenTransformer"+>GenTransformer</A+> = <SPAN CLASS="keyword"+>forall</SPAN+> a . <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/QuickCheck-1.1.0.0/Test-QuickCheck.html#t%3AGen"+>Gen</A+> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/QuickCheck-1.1.0.0/Test-QuickCheck.html#t%3AGen"+>Gen</A+> a</TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><SPAN CLASS="keyword"+>type</SPAN+> <A HREF="#t%3AMakePM"+>MakePM</A+> a = a -> <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3APatternMatch"+>PatternMatch</A+></TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><SPAN CLASS="keyword"+>data</SPAN+> <A HREF="#t%3AMakeResult"+>MakeResult</A+> a</TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3Atransform"+>transform</A+> :: <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a -> <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a</TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3Alift%27"+>lift'</A+> :: <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/QuickCheck-1.1.0.0/Test-QuickCheck.html#t%3AGen"+>Gen</A+> a -> <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a</TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3Aarbitrary%27"+>arbitrary'</A+> :: <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/QuickCheck-1.1.0.0/Test-QuickCheck.html#t%3AArbitrary"+>Arbitrary</A+> a => <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a</TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3Achoose%27"+>choose'</A+> :: <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/random-1.0.0.0/System-Random.html#t%3ARandom"+>Random</A+> a => (a, a) -> <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a</TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3Aelements%27"+>elements'</A+> :: [a] -> <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a</TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3Aoneof%27"+>oneof'</A+> :: [<A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a] -> <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a</TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3Afrequency%27"+>frequency'</A+> :: [(<A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Int.html#t%3AInt"+>Int</A+>, <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a)] -> <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a</TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3Asized%27"+>sized'</A+> :: (<A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Int.html#t%3AInt"+>Int</A+> -> <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a) -> <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a</TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3Aresize%27"+>resize'</A+> :: <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Int.html#t%3AInt"+>Int</A+> -> <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a -> <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a</TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3Amatch"+>match</A+> :: <SPAN CLASS="keyword"+>forall</SPAN+> a . <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Generics-Basics.html#t%3AData"+>Data</A+> a => <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakePM"+>MakePM</A+> a</TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3Aflat"+>flat</A+> :: <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/QuickCheck-1.1.0.0/Test-QuickCheck.html#t%3AArbitrary"+>Arbitrary</A+> a => <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a</TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3AfiniteListOf"+>finiteListOf</A+> :: <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a -> <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> [a]</TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3AinfiniteListOf"+>infiniteListOf</A+> :: <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a -> <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> [a]</TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3AlistOf"+>listOf</A+> :: <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a -> <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> [a]</TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="section1"+><A NAME="1"+>Basic framework+</A+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3Afunction"+></A+><B+>function</B+> :: <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakePM"+>MakePM</A+> a -> <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> b -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/QuickCheck-1.1.0.0/Test-QuickCheck.html#t%3AGen"+>Gen</A+> (a -> b)</TD+></TR+><TR+><TD CLASS="doc"+>Generator for continuous, not necessarily strict functions.+ Functions are generated by first generating pattern matches, and+ then generating a result.+</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3AfunctionTo"+></A+><B+>functionTo</B+> :: <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Generics-Basics.html#t%3AData"+>Data</A+> a => <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> b -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/QuickCheck-1.1.0.0/Test-QuickCheck.html#t%3AGen"+>Gen</A+> (a -> b)</TD+></TR+><TR+><TD CLASS="doc"+><P+><TT+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#v%3AfunctionTo"+>functionTo</A+></TT+> specialises <TT+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#v%3Afunction"+>function</A+></TT+>:+</P+><PRE+>+ <TT+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#v%3AfunctionTo"+>functionTo</A+></TT+> = <TT+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#v%3Afunction"+>function</A+></TT+> <TT+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#v%3Amatch"+>match</A+></TT+>+ </PRE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><SPAN CLASS="keyword"+>data</SPAN+> <A NAME="t%3APatternMatch"+></A+><B+>PatternMatch</B+> </TD+></TR+><TR+><TD CLASS="body"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="ndoc"+><TT+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3APatternMatch"+>PatternMatch</A+></TT+> packages up the possible outcomes of a pattern+ match in a style suitable for generating functions. A pattern match+ is a generator (<TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/QuickCheck-1.1.0.0/Test-QuickCheck.html#t%3AGen"+>Gen</A+></TT+>) transformer based on the top-level+ constructor, and a sequence (see+ <A HREF="http://www.soi.city.ac.uk/~ross/software/html/Data.Sequence.html"+>http://www.soi.city.ac.uk/~ross/software/html/Data.Sequence.html</A+>) of+ <TT+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3APatternMatch"+>PatternMatch</A+></TT+>es based on the children of that constructor.+</TD+></TR+><TR+><TD CLASS="section4"+>Constructors</TD+></TR+><TR+><TD CLASS="body"+><TABLE CLASS="vanilla" CELLSPACING="5" CELLPADDING="0"+><TR+><TD CLASS="arg"+><A NAME="v%3APatternMatch"+></A+><B+>PatternMatch</B+></TD+><TD CLASS="rdoc"+></TD+></TR+><TR+><TD CLASS="body" COLSPAN="2"+><TABLE CLASS="vanilla" CELLSPACING="1" CELLPADDING="0"+><TR+><TD CLASS="arg"+><A NAME="v%3Aapply"+></A+><B+>apply</B+> :: <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AGenTransformer"+>GenTransformer</A+></TD+><TD CLASS="rdoc"+>A generator transformer, in the style of <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/QuickCheck-1.1.0.0/Test-QuickCheck.html#v%3Acoarbitrary"+>coarbitrary</A+></TT+>.+</TD+></TR+><TR+><TD CLASS="arg"+><A NAME="v%3Amore"+></A+><B+>more</B+> :: (<A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/containers-0.1.0.0/Data-Sequence.html#t%3ASeq"+>Seq</A+> <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3APatternMatch"+>PatternMatch</A+>)</TD+><TD CLASS="rdoc"+>Further pattern matches made possible by this+ match.+</TD+></TR+></TABLE+></TD+></TR+></TABLE+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><SPAN CLASS="keyword"+>type</SPAN+> <A NAME="t%3AGenTransformer"+></A+><B+>GenTransformer</B+> = <SPAN CLASS="keyword"+>forall</SPAN+> a . <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/QuickCheck-1.1.0.0/Test-QuickCheck.html#t%3AGen"+>Gen</A+> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/QuickCheck-1.1.0.0/Test-QuickCheck.html#t%3AGen"+>Gen</A+> a</TD+></TR+><TR+><TD CLASS="doc"+>The type of a generator transformer.+</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><SPAN CLASS="keyword"+>type</SPAN+> <A NAME="t%3AMakePM"+></A+><B+>MakePM</B+> a = a -> <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3APatternMatch"+>PatternMatch</A+></TD+></TR+><TR+><TD CLASS="doc"+>The type of a <TT+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3APatternMatch"+>PatternMatch</A+></TT+> generator.+</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><SPAN CLASS="keyword"+>data</SPAN+> <A NAME="t%3AMakeResult"+></A+><B+>MakeResult</B+> a</TD+></TR+><TR+><TD CLASS="body"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="ndoc"+><P+>Monad for generating results given previously generated pattern+ matches.+</P+><P+>A <TT+><TT+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+></TT+> a</TT+> should be implemented almost as other generators for+ the type <TT+>a</TT+>, with the difference that <TT+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#v%3Atransform"+>transform</A+></TT+> should be+ used wherever the resulting function should be allowed to pattern+ match (typically for each constructor emitted). See example above.+</P+></TD+></TR+><TR+><TD CLASS="section4"+><IMG SRC="minus.gif" CLASS="coll" ONCLICK="toggle(this,'i:MakeResult')" ALT="show/hide"+> Instances</TD+></TR+><TR+><TD CLASS="body"+><DIV ID="i:MakeResult" STYLE="display:block;"+><TABLE CLASS="vanilla" CELLSPACING="1" CELLPADDING="0"+><TR+><TD CLASS="decl"+>??? a => <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Control-Monad.html#t%3AFunctor"+>Functor</A+> (<A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a)</TD+></TR+><TR+><TD CLASS="decl"+>??? a => <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Control-Monad.html#t%3AMonad"+>Monad</A+> (<A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a)</TD+></TR+></TABLE+></DIV+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3Atransform"+></A+><B+>transform</B+> :: <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a -> <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a</TD+></TR+><TR+><TD CLASS="doc"+><TT+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#v%3Atransform"+>transform</A+></TT+> makes sure that the pattern matches get to influence+ the generated value. See <TT+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+></TT+>.+</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="section1"+><A NAME="2"+>Liftings of some QuickCheck functionality+</A+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3Alift%27"+></A+><B+>lift'</B+> :: <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/QuickCheck-1.1.0.0/Test-QuickCheck.html#t%3AGen"+>Gen</A+> a -> <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a</TD+></TR+><TR+><TD CLASS="doc"+>Lifting of a <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/QuickCheck-1.1.0.0/Test-QuickCheck.html#t%3AGen"+>Gen</A+></TT+>.+</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3Aarbitrary%27"+></A+><B+>arbitrary'</B+> :: <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/QuickCheck-1.1.0.0/Test-QuickCheck.html#t%3AArbitrary"+>Arbitrary</A+> a => <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a</TD+></TR+><TR+><TD CLASS="doc"+>Lifting of <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/QuickCheck-1.1.0.0/Test-QuickCheck.html#v%3Aarbitrary"+>arbitrary</A+></TT+>.+</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3Achoose%27"+></A+><B+>choose'</B+> :: <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/random-1.0.0.0/System-Random.html#t%3ARandom"+>Random</A+> a => (a, a) -> <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a</TD+></TR+><TR+><TD CLASS="doc"+>Lifting of <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/QuickCheck-1.1.0.0/Test-QuickCheck.html#v%3Achoose"+>choose</A+></TT+>.+</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3Aelements%27"+></A+><B+>elements'</B+> :: [a] -> <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a</TD+></TR+><TR+><TD CLASS="doc"+>Lifting of <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/QuickCheck-1.1.0.0/Test-QuickCheck.html#v%3Aelements"+>elements</A+></TT+>.+</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3Aoneof%27"+></A+><B+>oneof'</B+> :: [<A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a] -> <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a</TD+></TR+><TR+><TD CLASS="doc"+>Lifting of <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/QuickCheck-1.1.0.0/Test-QuickCheck.html#v%3Aoneof"+>oneof</A+></TT+>.+</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3Afrequency%27"+></A+><B+>frequency'</B+> :: [(<A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Int.html#t%3AInt"+>Int</A+>, <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a)] -> <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a</TD+></TR+><TR+><TD CLASS="doc"+>Lifting of <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/QuickCheck-1.1.0.0/Test-QuickCheck.html#v%3Afrequency"+>frequency</A+></TT+>.+</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3Asized%27"+></A+><B+>sized'</B+> :: (<A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Int.html#t%3AInt"+>Int</A+> -> <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a) -> <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a</TD+></TR+><TR+><TD CLASS="doc"+>Lifting of <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/QuickCheck-1.1.0.0/Test-QuickCheck.html#v%3Asized"+>sized</A+></TT+>.+</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3Aresize%27"+></A+><B+>resize'</B+> :: <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Int.html#t%3AInt"+>Int</A+> -> <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a -> <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a</TD+></TR+><TR+><TD CLASS="doc"+>Lifting of <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/QuickCheck-1.1.0.0/Test-QuickCheck.html#v%3Aresize"+>resize</A+></TT+>.+</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="section1"+><A NAME="3"+>Generic <TT+>MakePM</TT+>+</A+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3Amatch"+></A+><B+>match</B+> :: <SPAN CLASS="keyword"+>forall</SPAN+> a . <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Generics-Basics.html#t%3AData"+>Data</A+> a => <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakePM"+>MakePM</A+> a</TD+></TR+><TR+><TD CLASS="doc"+>Generic implementation of <TT+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3APatternMatch"+>PatternMatch</A+></TT+> construction.+</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="section1"+><A NAME="4"+>Some <TT+>MakeResult</TT+>s+</A+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3Aflat"+></A+><B+>flat</B+> :: <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/QuickCheck-1.1.0.0/Test-QuickCheck.html#t%3AArbitrary"+>Arbitrary</A+> a => <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a</TD+></TR+><TR+><TD CLASS="doc"+>An implementation of <TT+><TT+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+></TT+> a</TT+> which is suitable when <TT+>a</TT+>+ is flat and has an <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/QuickCheck-1.1.0.0/Test-QuickCheck.html#t%3AArbitrary"+>Arbitrary</A+></TT+> instance. Yields bottoms around 10%+ of the time.+</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3AfiniteListOf"+></A+><B+>finiteListOf</B+> :: <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a -> <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> [a]</TD+></TR+><TR+><TD CLASS="doc"+>This <TT+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+></TT+> yields finite partial lists.+</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3AinfiniteListOf"+></A+><B+>infiniteListOf</B+> :: <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a -> <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> [a]</TD+></TR+><TR+><TD CLASS="doc"+>This <TT+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+></TT+> yields infinite partial lists.+</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3AlistOf"+></A+><B+>listOf</B+> :: <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> a -> <A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+> [a]</TD+></TR+><TR+><TD CLASS="doc"+>This <TT+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>MakeResult</A+></TT+> yields finite or infinite partial lists.+</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="botbar"+>Produced by <A HREF="http://www.haskell.org/haddock/"+>Haddock</A+> version 0.7</TD+></TR+></TABLE+></BODY+></HTML+>
+ docs/Test-ChasingBottoms-IsBottom.html view
@@ -0,0 +1,380 @@+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">+<!--Rendered using the Haskell Html Library v0.2-->+<HTML+><HEAD+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"+><TITLE+>Test.ChasingBottoms.IsBottom</TITLE+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"+><SCRIPT SRC="haddock.js" TYPE="text/javascript"+></SCRIPT+></HEAD+><BODY+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="topbar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "+></TD+><TD CLASS="title"+>Chasing Bottoms</TD+><TD CLASS="topbut"+><A HREF="index.html"+>Contents</A+></TD+><TD CLASS="topbut"+><A HREF="doc-index.html"+>Index</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="modulebar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><FONT SIZE="6"+>Test.ChasingBottoms.IsBottom</FONT+></TD+><TD ALIGN="right"+><TABLE CLASS="narrow" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="infohead"+>Portability</TD+><TD CLASS="infoval"+>non-portable (exceptions)</TD+></TR+><TR+><TD CLASS="infohead"+>Stability</TD+><TD CLASS="infoval"+>experimental</TD+></TR+><TR+><TD CLASS="infohead"+>Maintainer</TD+><TD CLASS="infoval"+>http://www.cs.chalmers.se/~nad/</TD+></TR+></TABLE+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+></TABLE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="section1"+>Description</TD+></TR+><TR+><TD CLASS="doc"+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="section1"+>Synopsis</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="body"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="decl"+><A HREF="#v%3AisBottom"+>isBottom</A+> :: a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Bool.html#t%3ABool"+>Bool</A+></TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3Abottom"+>bottom</A+> :: a</TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3AnonBottomError"+>nonBottomError</A+> :: <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Char.html#t%3AString"+>String</A+> -> a</TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3AisBottomTimeOut"+>isBottomTimeOut</A+> :: <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Maybe.html#t%3AMaybe"+>Maybe</A+> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Int.html#t%3AInt"+>Int</A+> -> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Bool.html#t%3ABool"+>Bool</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="section1"+>Documentation</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3AisBottom"+></A+><B+>isBottom</B+> :: a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Bool.html#t%3ABool"+>Bool</A+></TD+></TR+><TR+><TD CLASS="doc"+><P+><TT+><TT+><A HREF="Test-ChasingBottoms-IsBottom.html#v%3AisBottom"+>isBottom</A+></TT+> a</TT+> returns <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Bool.html#v%3AFalse"+>False</A+></TT+> if <TT+>a</TT+> is distinct from bottom. If+ <TT+>a</TT+> equals bottom and results in an exception which is caught by+ <TT+><A HREF="Test-ChasingBottoms-IsBottom.html#v%3AisBottom"+>isBottom</A+></TT+>, and this exception is of a certain kind (see below),+ then <TT+><TT+><A HREF="Test-ChasingBottoms-IsBottom.html#v%3AisBottom"+>isBottom</A+></TT+> a = <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Bool.html#v%3ATrue"+>True</A+></TT+></TT+>. Other caught exceptions are+ re-thrown. If <TT+>a</TT+> never reaches a weak head normal form and+ never throws an exception, then <TT+><TT+><A HREF="Test-ChasingBottoms-IsBottom.html#v%3AisBottom"+>isBottom</A+></TT+> a</TT+> never terminates.+</P+><P+>The exceptions that yield <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Bool.html#v%3ATrue"+>True</A+></TT+> are those that correspond to+ "pure bottoms", i.e. bottoms that can originate in pure code.+ Assertions are excluded, since their behaviour depends on compiler+ flags (not pure, and a failed assertion should really yield an+ exception and nothing else). The same applies to arithmetic+ exceptions (machine dependent, except possibly for+ <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Control-Exception.html#t%3ADivideByZero"+>DivideByZero</A+></TT+>, but the value infinity makes that+ case unclear as well).+</P+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3Abottom"+></A+><B+>bottom</B+> :: a</TD+></TR+><TR+><TD CLASS="doc"+><TT+><A HREF="Test-ChasingBottoms-IsBottom.html#v%3Abottom"+>bottom</A+></TT+> generates a bottom that is suitable for testing using+ <TT+><A HREF="Test-ChasingBottoms-IsBottom.html#v%3AisBottom"+>isBottom</A+></TT+>.+</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3AnonBottomError"+></A+><B+>nonBottomError</B+> :: <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Char.html#t%3AString"+>String</A+> -> a</TD+></TR+><TR+><TD CLASS="doc"+><TT+><TT+><A HREF="Test-ChasingBottoms-IsBottom.html#v%3AnonBottomError"+>nonBottomError</A+></TT+> s</TT+> raises an exception (<TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Control-Exception.html#v%3AAssertionFailed"+>AssertionFailed</A+></TT+>) that+ is not caught by <TT+><A HREF="Test-ChasingBottoms-IsBottom.html#v%3AisBottom"+>isBottom</A+></TT+>. Use <TT+>s</TT+> to describe the exception.+</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3AisBottomTimeOut"+></A+><B+>isBottomTimeOut</B+> :: <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Maybe.html#t%3AMaybe"+>Maybe</A+> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Int.html#t%3AInt"+>Int</A+> -> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Bool.html#t%3ABool"+>Bool</A+></TD+></TR+><TR+><TD CLASS="doc"+><P+><TT+><TT+><A HREF="Test-ChasingBottoms-IsBottom.html#v%3AisBottomTimeOut"+>isBottomTimeOut</A+></TT+> timeOutLimit</TT+> works like <TT+><A HREF="Test-ChasingBottoms-IsBottom.html#v%3AisBottom"+>isBottom</A+></TT+>, but if+ <TT+>timeOutLimit</TT+> is <TT+><TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Maybe.html#v%3AJust"+>Just</A+></TT+> lim</TT+>, then computations taking more than+ <TT+>lim</TT+> seconds are also considered to be equal to bottom. Note that+ this is a very crude approximation of what a bottom is. Also note+ that this "function" may return different answers upon different+ invocations. Take it for what it is worth.+</P+><P+><TT+><A HREF="Test-ChasingBottoms-IsBottom.html#v%3AisBottomTimeOut"+>isBottomTimeOut</A+></TT+> is subject to all the same scheduling vagaries as+ <TT+><A HREF="Test-ChasingBottoms-TimeOut.html#v%3AtimeOut"+>timeOut</A+></TT+>.+</P+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="botbar"+>Produced by <A HREF="http://www.haskell.org/haddock/"+>Haddock</A+> version 0.7</TD+></TR+></TABLE+></BODY+></HTML+>
+ docs/Test-ChasingBottoms-Nat.html view
@@ -0,0 +1,484 @@+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">+<!--Rendered using the Haskell Html Library v0.2-->+<HTML+><HEAD+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"+><TITLE+>Test.ChasingBottoms.Nat</TITLE+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"+><SCRIPT SRC="haddock.js" TYPE="text/javascript"+></SCRIPT+></HEAD+><BODY+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="topbar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "+></TD+><TD CLASS="title"+>Chasing Bottoms</TD+><TD CLASS="topbut"+><A HREF="index.html"+>Contents</A+></TD+><TD CLASS="topbut"+><A HREF="doc-index.html"+>Index</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="modulebar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><FONT SIZE="6"+>Test.ChasingBottoms.Nat</FONT+></TD+><TD ALIGN="right"+><TABLE CLASS="narrow" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="infohead"+>Portability</TD+><TD CLASS="infoval"+>non-portable (GHC-specific)</TD+></TR+><TR+><TD CLASS="infohead"+>Stability</TD+><TD CLASS="infoval"+>experimental</TD+></TR+><TR+><TD CLASS="infohead"+>Maintainer</TD+><TD CLASS="infoval"+>http://www.cs.chalmers.se/~nad/</TD+></TR+></TABLE+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+></TABLE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="section1"+>Description</TD+></TR+><TR+><TD CLASS="doc"+>A simple implementation of natural numbers on top of <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Prelude.html#t%3AInteger"+>Integer</A+></TT+>s.+ Note that since <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Prelude.html#t%3AInteger"+>Integer</A+></TT+>s are used there is no infinite natural+ number; in other words, <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Prelude.html#v%3Asucc"+>succ</A+></TT+> is strict.+</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="section1"+>Synopsis</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="body"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="decl"+><SPAN CLASS="keyword"+>data</SPAN+> <A HREF="#t%3ANat"+>Nat</A+> </TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3AisSucc"+>isSucc</A+> :: <A HREF="Test-ChasingBottoms-Nat.html#t%3ANat"+>Nat</A+> -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Bool.html#t%3ABool"+>Bool</A+></TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3AfromSucc"+>fromSucc</A+> :: <A HREF="Test-ChasingBottoms-Nat.html#t%3ANat"+>Nat</A+> -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Maybe.html#t%3AMaybe"+>Maybe</A+> <A HREF="Test-ChasingBottoms-Nat.html#t%3ANat"+>Nat</A+></TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3Anatrec"+>natrec</A+> :: a -> (<A HREF="Test-ChasingBottoms-Nat.html#t%3ANat"+>Nat</A+> -> a -> a) -> <A HREF="Test-ChasingBottoms-Nat.html#t%3ANat"+>Nat</A+> -> a</TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3AfoldN"+>foldN</A+> :: a -> (a -> a) -> <A HREF="Test-ChasingBottoms-Nat.html#t%3ANat"+>Nat</A+> -> a</TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="section1"+>Documentation</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><SPAN CLASS="keyword"+>data</SPAN+> <A NAME="t%3ANat"+></A+><B+>Nat</B+> </TD+></TR+><TR+><TD CLASS="body"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="ndoc"+><P+>Natural numbers.+</P+><P+>No <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Generics-Basics.html#t%3AData"+>Data</A+></TT+> instance is provided since the+ implementation should be abstract.+</P+></TD+></TR+><TR+><TD CLASS="section4"+><IMG SRC="minus.gif" CLASS="coll" ONCLICK="toggle(this,'i:Nat')" ALT="show/hide"+> Instances</TD+></TR+><TR+><TD CLASS="body"+><DIV ID="i:Nat" STYLE="display:block;"+><TABLE CLASS="vanilla" CELLSPACING="1" CELLPADDING="0"+><TR+><TD CLASS="decl"+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/QuickCheck-1.1.0.0/Test-QuickCheck.html#t%3AArbitrary"+>Arbitrary</A+> <A HREF="Test-ChasingBottoms-Nat.html#t%3ANat"+>Nat</A+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Prelude.html#t%3AEnum"+>Enum</A+> <A HREF="Test-ChasingBottoms-Nat.html#t%3ANat"+>Nat</A+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Eq.html#t%3AEq"+>Eq</A+> <A HREF="Test-ChasingBottoms-Nat.html#t%3ANat"+>Nat</A+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Prelude.html#t%3AIntegral"+>Integral</A+> <A HREF="Test-ChasingBottoms-Nat.html#t%3ANat"+>Nat</A+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Prelude.html#t%3ANum"+>Num</A+> <A HREF="Test-ChasingBottoms-Nat.html#t%3ANat"+>Nat</A+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Ord.html#t%3AOrd"+>Ord</A+> <A HREF="Test-ChasingBottoms-Nat.html#t%3ANat"+>Nat</A+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Prelude.html#t%3AReal"+>Real</A+> <A HREF="Test-ChasingBottoms-Nat.html#t%3ANat"+>Nat</A+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Text-Show.html#t%3AShow"+>Show</A+> <A HREF="Test-ChasingBottoms-Nat.html#t%3ANat"+>Nat</A+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Typeable.html#t%3ATypeable"+>Typeable</A+> <A HREF="Test-ChasingBottoms-Nat.html#t%3ANat"+>Nat</A+></TD+></TR+></TABLE+></DIV+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3AisSucc"+></A+><B+>isSucc</B+> :: <A HREF="Test-ChasingBottoms-Nat.html#t%3ANat"+>Nat</A+> -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Bool.html#t%3ABool"+>Bool</A+></TD+></TR+><TR+><TD CLASS="doc"+><TT+><TT+><A HREF="Test-ChasingBottoms-Nat.html#v%3AisSucc"+>isSucc</A+></TT+> 0 == <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Bool.html#v%3AFalse"+>False</A+></TT+></TT+>, for other total natural numbers it is <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Bool.html#v%3ATrue"+>True</A+></TT+>.+</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3AfromSucc"+></A+><B+>fromSucc</B+> :: <A HREF="Test-ChasingBottoms-Nat.html#t%3ANat"+>Nat</A+> -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Maybe.html#t%3AMaybe"+>Maybe</A+> <A HREF="Test-ChasingBottoms-Nat.html#t%3ANat"+>Nat</A+></TD+></TR+><TR+><TD CLASS="doc"+><TT+><TT+><A HREF="Test-ChasingBottoms-Nat.html#v%3AfromSucc"+>fromSucc</A+></TT+> 0 == <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Maybe.html#v%3ANothing"+>Nothing</A+></TT+></TT+>, <TT+><TT+><A HREF="Test-ChasingBottoms-Nat.html#v%3AfromSucc"+>fromSucc</A+></TT+> (n+1) == <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Maybe.html#v%3AJust"+>Just</A+></TT+> n</TT+> for a+ total natural number <TT+>n</TT+>.+</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3Anatrec"+></A+><B+>natrec</B+> :: a -> (<A HREF="Test-ChasingBottoms-Nat.html#t%3ANat"+>Nat</A+> -> a -> a) -> <A HREF="Test-ChasingBottoms-Nat.html#t%3ANat"+>Nat</A+> -> a</TD+></TR+><TR+><TD CLASS="doc"+><TT+><A HREF="Test-ChasingBottoms-Nat.html#v%3Anatrec"+>natrec</A+></TT+> performs primitive recursion on natural numbers.+</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3AfoldN"+></A+><B+>foldN</B+> :: a -> (a -> a) -> <A HREF="Test-ChasingBottoms-Nat.html#t%3ANat"+>Nat</A+> -> a</TD+></TR+><TR+><TD CLASS="doc"+><P+><TT+><A HREF="Test-ChasingBottoms-Nat.html#v%3AfoldN"+>foldN</A+></TT+> is a fold on natural numbers:+</P+><PRE+>+ <TT+><A HREF="Test-ChasingBottoms-Nat.html#v%3AfoldN"+>foldN</A+></TT+> g h = <TT+><A HREF="Test-ChasingBottoms-Nat.html#v%3Anatrec"+>natrec</A+></TT+> g (<TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Tuple.html#v%3Acurry"+>curry</A+></TT+> <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Prelude.html#v%3A%24"+>$</A+></TT+> h . <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Tuple.html#v%3Asnd"+>snd</A+></TT+>)+ </PRE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="botbar"+>Produced by <A HREF="http://www.haskell.org/haddock/"+>Haddock</A+> version 0.7</TD+></TR+></TABLE+></BODY+></HTML+>
+ docs/Test-ChasingBottoms-SemanticOrd.html view
@@ -0,0 +1,940 @@+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">+<!--Rendered using the Haskell Html Library v0.2-->+<HTML+><HEAD+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"+><TITLE+>Test.ChasingBottoms.SemanticOrd</TITLE+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"+><SCRIPT SRC="haddock.js" TYPE="text/javascript"+></SCRIPT+></HEAD+><BODY+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="topbar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "+></TD+><TD CLASS="title"+>Chasing Bottoms</TD+><TD CLASS="topbut"+><A HREF="index.html"+>Contents</A+></TD+><TD CLASS="topbut"+><A HREF="doc-index.html"+>Index</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="modulebar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><FONT SIZE="6"+>Test.ChasingBottoms.SemanticOrd</FONT+></TD+><TD ALIGN="right"+><TABLE CLASS="narrow" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="infohead"+>Portability</TD+><TD CLASS="infoval"+>non-portable (GHC-specific)</TD+></TR+><TR+><TD CLASS="infohead"+>Stability</TD+><TD CLASS="infoval"+>experimental</TD+></TR+><TR+><TD CLASS="infohead"+>Maintainer</TD+><TD CLASS="infoval"+>http://www.cs.chalmers.se/~nad/</TD+></TR+></TABLE+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+></TABLE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="section1"+>Description</TD+></TR+><TR+><TD CLASS="doc"+><P+>Generic semantic equality and order. The semantic order referred+ to is that of a typical CPO for Haskell types, where e.g. <TT+>(<TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Bool.html#v%3ATrue"+>True</A+></TT+>,+ <TT+><A HREF="Test-ChasingBottoms-IsBottom.html#v%3Abottom"+>bottom</A+></TT+>) <TT+><A HREF="Test-ChasingBottoms-SemanticOrd.html#v%3A%3C%3D%21"+><=!</A+></TT+> (<TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Bool.html#v%3ATrue"+>True</A+></TT+>, <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Bool.html#v%3AFalse"+>False</A+></TT+>)</TT+>, but where <TT+>(<TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Bool.html#v%3ATrue"+>True</A+></TT+>, <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Bool.html#v%3ATrue"+>True</A+></TT+>)</TT+>+ and <TT+>(<TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Bool.html#v%3ATrue"+>True</A+></TT+>, <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Bool.html#v%3AFalse"+>False</A+></TT+>)</TT+> are incomparable.+</P+><P+>The implementation is based on <TT+><A HREF="Test-ChasingBottoms-IsBottom.html#v%3AisBottom"+>isBottom</A+></TT+>, and has the same+ limitations. Note that non-bottom functions are not handled by any+ of the functions described below.+</P+><P+>One could imagine using QuickCheck for testing equality of+ functions, but I have not managed to tweak the type system so that+ it can be done transparently.+</P+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="section1"+>Synopsis</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="body"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="decl"+><SPAN CLASS="keyword"+>data</SPAN+> <A HREF="#t%3ATweak"+>Tweak</A+> = <A HREF="#v%3ATweak"+>Tweak</A+> {<TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="recfield"+><A HREF="#v%3AapproxDepth"+>approxDepth</A+> :: (<A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Maybe.html#t%3AMaybe"+>Maybe</A+> <A HREF="Test-ChasingBottoms-Nat.html#t%3ANat"+>Nat</A+>)</TD+></TR+><TR+><TD CLASS="recfield"+><A HREF="#v%3AtimeOutLimit"+>timeOutLimit</A+> :: (<A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Maybe.html#t%3AMaybe"+>Maybe</A+> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Int.html#t%3AInt"+>Int</A+>)</TD+></TR+></TABLE+>}</TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3AnoTweak"+>noTweak</A+> :: <A HREF="Test-ChasingBottoms-SemanticOrd.html#t%3ATweak"+>Tweak</A+></TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><SPAN CLASS="keyword"+>class</SPAN+> <A HREF="#t%3ASemanticEq"+>SemanticEq</A+> a <SPAN CLASS="keyword"+>where</SPAN+></TD+></TR+><TR+><TD CLASS="body"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="decl"+><A HREF="#v%3A%3D%3D%21"+>(==!)</A+> :: a -> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Bool.html#t%3ABool"+>Bool</A+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3A%2F%3D%21"+>(/=!)</A+> :: a -> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Bool.html#t%3ABool"+>Bool</A+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3AsemanticEq"+>semanticEq</A+> :: <A HREF="Test-ChasingBottoms-SemanticOrd.html#t%3ATweak"+>Tweak</A+> -> a -> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Bool.html#t%3ABool"+>Bool</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><SPAN CLASS="keyword"+>class</SPAN+> <A HREF="Test-ChasingBottoms-SemanticOrd.html#t%3ASemanticEq"+>SemanticEq</A+> a => <A HREF="#t%3ASemanticOrd"+>SemanticOrd</A+> a <SPAN CLASS="keyword"+>where</SPAN+></TD+></TR+><TR+><TD CLASS="body"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="decl"+><A HREF="#v%3A%3C%21"+>(<!)</A+> :: a -> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Bool.html#t%3ABool"+>Bool</A+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3A%3C%3D%21"+>(<=!)</A+> :: a -> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Bool.html#t%3ABool"+>Bool</A+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3A%3E%3D%21"+>(>=!)</A+> :: a -> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Bool.html#t%3ABool"+>Bool</A+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3A%3E%21"+>(>!)</A+> :: a -> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Bool.html#t%3ABool"+>Bool</A+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3AsemanticCompare"+>semanticCompare</A+> :: <A HREF="Test-ChasingBottoms-SemanticOrd.html#t%3ATweak"+>Tweak</A+> -> a -> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Maybe.html#t%3AMaybe"+>Maybe</A+> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Ord.html#t%3AOrdering"+>Ordering</A+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3A%5C%2F%21"+>(\/!)</A+> :: a -> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Maybe.html#t%3AMaybe"+>Maybe</A+> a</TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3A%2F%5C%21"+>(/\!)</A+> :: a -> a -> a</TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3AsemanticJoin"+>semanticJoin</A+> :: <A HREF="Test-ChasingBottoms-SemanticOrd.html#t%3ATweak"+>Tweak</A+> -> a -> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Maybe.html#t%3AMaybe"+>Maybe</A+> a</TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3AsemanticMeet"+>semanticMeet</A+> :: <A HREF="Test-ChasingBottoms-SemanticOrd.html#t%3ATweak"+>Tweak</A+> -> a -> a -> a</TD+></TR+></TABLE+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="section1"+>Documentation</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><SPAN CLASS="keyword"+>data</SPAN+> <A NAME="t%3ATweak"+></A+><B+>Tweak</B+> </TD+></TR+><TR+><TD CLASS="body"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="ndoc"+>The behaviour of some of the functions below can be tweaked.+</TD+></TR+><TR+><TD CLASS="section4"+>Constructors</TD+></TR+><TR+><TD CLASS="body"+><TABLE CLASS="vanilla" CELLSPACING="5" CELLPADDING="0"+><TR+><TD CLASS="arg"+><A NAME="v%3ATweak"+></A+><B+>Tweak</B+></TD+><TD CLASS="rdoc"+></TD+></TR+><TR+><TD CLASS="body" COLSPAN="2"+><TABLE CLASS="vanilla" CELLSPACING="1" CELLPADDING="0"+><TR+><TD CLASS="arg"+><A NAME="v%3AapproxDepth"+></A+><B+>approxDepth</B+> :: (<A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Maybe.html#t%3AMaybe"+>Maybe</A+> <A HREF="Test-ChasingBottoms-Nat.html#t%3ANat"+>Nat</A+>)</TD+><TD CLASS="rdoc"+>If equal to <TT+><TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Maybe.html#v%3AJust"+>Just</A+></TT+> n</TT+>, an <TT+><TT+><A HREF="Test-ChasingBottoms-Approx.html#v%3AapproxAll"+>approxAll</A+></TT+> n</TT+> is performed on+ all arguments before doing whatever the function is supposed to+ be doing.+</TD+></TR+><TR+><TD CLASS="arg"+><A NAME="v%3AtimeOutLimit"+></A+><B+>timeOutLimit</B+> :: (<A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Maybe.html#t%3AMaybe"+>Maybe</A+> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Int.html#t%3AInt"+>Int</A+>)</TD+><TD CLASS="rdoc"+>If equal to <TT+><TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Maybe.html#v%3AJust"+>Just</A+></TT+> n</TT+>, then all computations that take more+ than <TT+>n</TT+> seconds to complete are considered to be equal to+ <TT+><A HREF="Test-ChasingBottoms-IsBottom.html#v%3Abottom"+>bottom</A+></TT+>. This functionality is implemented using+ <TT+><A HREF="Test-ChasingBottoms-IsBottom.html#v%3AisBottomTimeOut"+>isBottomTimeOut</A+></TT+>.+</TD+></TR+></TABLE+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="section4"+><IMG SRC="minus.gif" CLASS="coll" ONCLICK="toggle(this,'i:Tweak')" ALT="show/hide"+> Instances</TD+></TR+><TR+><TD CLASS="body"+><DIV ID="i:Tweak" STYLE="display:block;"+><TABLE CLASS="vanilla" CELLSPACING="1" CELLPADDING="0"+><TR+><TD CLASS="decl"+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Eq.html#t%3AEq"+>Eq</A+> <A HREF="Test-ChasingBottoms-SemanticOrd.html#t%3ATweak"+>Tweak</A+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Ord.html#t%3AOrd"+>Ord</A+> <A HREF="Test-ChasingBottoms-SemanticOrd.html#t%3ATweak"+>Tweak</A+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Text-Show.html#t%3AShow"+>Show</A+> <A HREF="Test-ChasingBottoms-SemanticOrd.html#t%3ATweak"+>Tweak</A+></TD+></TR+></TABLE+></DIV+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3AnoTweak"+></A+><B+>noTweak</B+> :: <A HREF="Test-ChasingBottoms-SemanticOrd.html#t%3ATweak"+>Tweak</A+></TD+></TR+><TR+><TD CLASS="doc"+>No tweak (both fields are <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Maybe.html#v%3ANothing"+>Nothing</A+></TT+>).+</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><SPAN CLASS="keyword"+>class</SPAN+> <A NAME="t%3ASemanticEq"+></A+><B+>SemanticEq</B+> a <SPAN CLASS="keyword"+>where</SPAN+></TD+></TR+><TR+><TD CLASS="body"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="ndoc"+><TT+><A HREF="Test-ChasingBottoms-SemanticOrd.html#t%3ASemanticEq"+>SemanticEq</A+></TT+> contains methods for testing whether two terms are+ semantically equal.+</TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="section4"+>Methods</TD+></TR+><TR+><TD CLASS="body"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="decl"+><A NAME="v%3A%3D%3D%21"+></A+><B+>(==!)</B+> :: a -> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Bool.html#t%3ABool"+>Bool</A+></TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3A%2F%3D%21"+></A+><B+>(/=!)</B+> :: a -> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Bool.html#t%3ABool"+>Bool</A+></TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3AsemanticEq"+></A+><B+>semanticEq</B+> :: <A HREF="Test-ChasingBottoms-SemanticOrd.html#t%3ATweak"+>Tweak</A+> -> a -> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Bool.html#t%3ABool"+>Bool</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="section4"+><IMG SRC="minus.gif" CLASS="coll" ONCLICK="toggle(this,'i:SemanticEq')" ALT="show/hide"+> Instances</TD+></TR+><TR+><TD CLASS="body"+><DIV ID="i:SemanticEq" STYLE="display:block;"+><TABLE CLASS="vanilla" CELLSPACING="1" CELLPADDING="0"+><TR+><TD CLASS="decl"+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Generics-Basics.html#t%3AData"+>Data</A+> a => <A HREF="Test-ChasingBottoms-SemanticOrd.html#t%3ASemanticEq"+>SemanticEq</A+> a</TD+></TR+></TABLE+></DIV+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><SPAN CLASS="keyword"+>class</SPAN+> <A HREF="Test-ChasingBottoms-SemanticOrd.html#t%3ASemanticEq"+>SemanticEq</A+> a => <A NAME="t%3ASemanticOrd"+></A+><B+>SemanticOrd</B+> a <SPAN CLASS="keyword"+>where</SPAN+></TD+></TR+><TR+><TD CLASS="body"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="ndoc"+><TT+><A HREF="Test-ChasingBottoms-SemanticOrd.html#t%3ASemanticOrd"+>SemanticOrd</A+></TT+> contains methods for testing whether two terms are+ related according to the semantic domain ordering.+</TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="section4"+>Methods</TD+></TR+><TR+><TD CLASS="body"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="decl"+><A NAME="v%3A%3C%21"+></A+><B+>(<!)</B+> :: a -> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Bool.html#t%3ABool"+>Bool</A+></TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3A%3C%3D%21"+></A+><B+>(<=!)</B+> :: a -> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Bool.html#t%3ABool"+>Bool</A+></TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3A%3E%3D%21"+></A+><B+>(>=!)</B+> :: a -> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Bool.html#t%3ABool"+>Bool</A+></TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3A%3E%21"+></A+><B+>(>!)</B+> :: a -> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Bool.html#t%3ABool"+>Bool</A+></TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3AsemanticCompare"+></A+><B+>semanticCompare</B+> :: <A HREF="Test-ChasingBottoms-SemanticOrd.html#t%3ATweak"+>Tweak</A+> -> a -> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Maybe.html#t%3AMaybe"+>Maybe</A+> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Ord.html#t%3AOrdering"+>Ordering</A+></TD+></TR+><TR+><TD CLASS="doc"+><TT+><TT+><A HREF="Test-ChasingBottoms-SemanticOrd.html#v%3AsemanticCompare"+>semanticCompare</A+></TT+> tweak x y</TT+> returns <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Maybe.html#v%3ANothing"+>Nothing</A+></TT+> if <TT+>x</TT+> and <TT+>y</TT+> are+ incomparable, and <TT+><TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Maybe.html#v%3AJust"+>Just</A+></TT+> o</TT+> otherwise, where <TT+>o :: <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Ord.html#t%3AOrdering"+>Ordering</A+></TT+></TT+>+ represents the relation between <TT+>x</TT+> and <TT+>y</TT+>.+</TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3A%5C%2F%21"+></A+><B+>(\/!)</B+> :: a -> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Maybe.html#t%3AMaybe"+>Maybe</A+> a</TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3A%2F%5C%21"+></A+><B+>(/\!)</B+> :: a -> a -> a</TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3AsemanticJoin"+></A+><B+>semanticJoin</B+> :: <A HREF="Test-ChasingBottoms-SemanticOrd.html#t%3ATweak"+>Tweak</A+> -> a -> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Maybe.html#t%3AMaybe"+>Maybe</A+> a</TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3AsemanticMeet"+></A+><B+>semanticMeet</B+> :: <A HREF="Test-ChasingBottoms-SemanticOrd.html#t%3ATweak"+>Tweak</A+> -> a -> a -> a</TD+></TR+><TR+><TD CLASS="doc"+><TT+>x <TT+><A HREF="Test-ChasingBottoms-SemanticOrd.html#v%3A%5C%2F%21"+>\/!</A+></TT+> y</TT+> and <TT+>x <TT+><A HREF="Test-ChasingBottoms-SemanticOrd.html#v%3A%2F%5C%21"+>/\!</A+></TT+> y</TT+> compute the least upper and greatest+ lower bounds, respectively, of <TT+>x</TT+> and <TT+>y</TT+> in the semantical+ domain ordering. Note that the least upper bound may not always+ exist.+ This functionality was implemented just because it was+ possible (and to provide analogues of <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Ord.html#v%3Amax"+>max</A+></TT+> and <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Ord.html#v%3Amin"+>min</A+></TT+> in the <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Ord.html#t%3AOrd"+>Ord</A+></TT+>+ class). If anyone finds any use for it, please let me know.+</TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="section4"+><IMG SRC="minus.gif" CLASS="coll" ONCLICK="toggle(this,'i:SemanticOrd')" ALT="show/hide"+> Instances</TD+></TR+><TR+><TD CLASS="body"+><DIV ID="i:SemanticOrd" STYLE="display:block;"+><TABLE CLASS="vanilla" CELLSPACING="1" CELLPADDING="0"+><TR+><TD CLASS="decl"+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Generics-Basics.html#t%3AData"+>Data</A+> a => <A HREF="Test-ChasingBottoms-SemanticOrd.html#t%3ASemanticOrd"+>SemanticOrd</A+> a</TD+></TR+></TABLE+></DIV+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="botbar"+>Produced by <A HREF="http://www.haskell.org/haddock/"+>Haddock</A+> version 0.7</TD+></TR+></TABLE+></BODY+></HTML+>
+ docs/Test-ChasingBottoms-TimeOut.html view
@@ -0,0 +1,612 @@+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">+<!--Rendered using the Haskell Html Library v0.2-->+<HTML+><HEAD+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"+><TITLE+>Test.ChasingBottoms.TimeOut</TITLE+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"+><SCRIPT SRC="haddock.js" TYPE="text/javascript"+></SCRIPT+></HEAD+><BODY+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="topbar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "+></TD+><TD CLASS="title"+>Chasing Bottoms</TD+><TD CLASS="topbut"+><A HREF="index.html"+>Contents</A+></TD+><TD CLASS="topbut"+><A HREF="doc-index.html"+>Index</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="modulebar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><FONT SIZE="6"+>Test.ChasingBottoms.TimeOut</FONT+></TD+><TD ALIGN="right"+><TABLE CLASS="narrow" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="infohead"+>Portability</TD+><TD CLASS="infoval"+>non-portable (preemptive scheduling)</TD+></TR+><TR+><TD CLASS="infohead"+>Stability</TD+><TD CLASS="infoval"+>experimental</TD+></TR+><TR+><TD CLASS="infohead"+>Maintainer</TD+><TD CLASS="infoval"+>http://www.cs.chalmers.se/~nad/</TD+></TR+></TABLE+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+></TABLE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="section1"+>Description</TD+></TR+><TR+><TD CLASS="doc"+><P+>When dealing with "hard bottoms", i.e. non-terminating+ computations that do not result in exceptions, the following functions+ may be handy.+</P+><P+>Note that a computation is considered to have terminated when it+ has reached weak head normal form (i.e. something distinct from+ bottom).+</P+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="section1"+>Synopsis</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="body"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="decl"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="decl"+><SPAN CLASS="keyword"+>data</SPAN+> <A HREF="#t%3AResult"+>Result</A+> a</TD+></TR+><TR+><TD CLASS="body"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="decl"+>= <A HREF="#v%3AValue"+>Value</A+> a</TD+></TR+><TR+><TD CLASS="decl"+>| <A HREF="#v%3ANonTermination"+>NonTermination</A+></TD+></TR+><TR+><TD CLASS="decl"+>| <A HREF="#v%3AException"+>Exception</A+> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Control-Exception.html#t%3AException"+>Exception</A+></TD+></TR+></TABLE+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3AtimeOut"+>timeOut</A+> :: <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Int.html#t%3AInt"+>Int</A+> -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/System-IO.html#t%3AIO"+>IO</A+> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/System-IO.html#t%3AIO"+>IO</A+> (<A HREF="Test-ChasingBottoms-TimeOut.html#t%3AResult"+>Result</A+> a)</TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3AtimeOut%27"+>timeOut'</A+> :: <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Int.html#t%3AInt"+>Int</A+> -> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/System-IO.html#t%3AIO"+>IO</A+> (<A HREF="Test-ChasingBottoms-TimeOut.html#t%3AResult"+>Result</A+> a)</TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3AtimeOutMicro"+>timeOutMicro</A+> :: <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Int.html#t%3AInt"+>Int</A+> -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/System-IO.html#t%3AIO"+>IO</A+> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/System-IO.html#t%3AIO"+>IO</A+> (<A HREF="Test-ChasingBottoms-TimeOut.html#t%3AResult"+>Result</A+> a)</TD+></TR+><TR+><TD CLASS="s8"+></TD+></TR+><TR+><TD CLASS="decl"+><A HREF="#v%3AtimeOutMicro%27"+>timeOutMicro'</A+> :: <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Int.html#t%3AInt"+>Int</A+> -> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/System-IO.html#t%3AIO"+>IO</A+> (<A HREF="Test-ChasingBottoms-TimeOut.html#t%3AResult"+>Result</A+> a)</TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="section1"+>Documentation</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><SPAN CLASS="keyword"+>data</SPAN+> <A NAME="t%3AResult"+></A+><B+>Result</B+> a</TD+></TR+><TR+><TD CLASS="body"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="section4"+>Constructors</TD+></TR+><TR+><TD CLASS="body"+><TABLE CLASS="vanilla" CELLSPACING="1" CELLPADDING="0"+><TR+><TD CLASS="arg"+><A NAME="v%3AValue"+></A+><B+>Value</B+> a</TD+><TD CLASS="rdoc"+></TD+></TR+><TR+><TD CLASS="arg"+><A NAME="v%3ANonTermination"+></A+><B+>NonTermination</B+></TD+><TD CLASS="rdoc"+></TD+></TR+><TR+><TD CLASS="arg"+><A NAME="v%3AException"+></A+><B+>Exception</B+> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Control-Exception.html#t%3AException"+>Exception</A+></TD+><TD CLASS="rdoc"+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="section4"+><IMG SRC="minus.gif" CLASS="coll" ONCLICK="toggle(this,'i:Result')" ALT="show/hide"+> Instances</TD+></TR+><TR+><TD CLASS="body"+><DIV ID="i:Result" STYLE="display:block;"+><TABLE CLASS="vanilla" CELLSPACING="1" CELLPADDING="0"+><TR+><TD CLASS="decl"+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Eq.html#t%3AEq"+>Eq</A+> a => <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Eq.html#t%3AEq"+>Eq</A+> (<A HREF="Test-ChasingBottoms-TimeOut.html#t%3AResult"+>Result</A+> a)</TD+></TR+><TR+><TD CLASS="decl"+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Text-Show.html#t%3AShow"+>Show</A+> a => <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Text-Show.html#t%3AShow"+>Show</A+> (<A HREF="Test-ChasingBottoms-TimeOut.html#t%3AResult"+>Result</A+> a)</TD+></TR+><TR+><TD CLASS="decl"+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Typeable.html#t%3ATypeable"+>Typeable</A+> a => <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Typeable.html#t%3ATypeable"+>Typeable</A+> (<A HREF="Test-ChasingBottoms-TimeOut.html#t%3AResult"+>Result</A+> a)</TD+></TR+></TABLE+></DIV+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3AtimeOut"+></A+><B+>timeOut</B+> :: <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Int.html#t%3AInt"+>Int</A+> -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/System-IO.html#t%3AIO"+>IO</A+> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/System-IO.html#t%3AIO"+>IO</A+> (<A HREF="Test-ChasingBottoms-TimeOut.html#t%3AResult"+>Result</A+> a)</TD+></TR+><TR+><TD CLASS="doc"+><P+><TT+><TT+><A HREF="Test-ChasingBottoms-TimeOut.html#v%3AtimeOut"+>timeOut</A+></TT+> n c</TT+> runs <TT+>c</TT+> for at most <TT+>n</TT+> seconds (modulo+ scheduling issues).+</P+><UL+><LI+> If the computation terminates before that, then+ <TT+><TT+><A HREF="Test-ChasingBottoms-TimeOut.html#v%3AValue"+>Value</A+></TT+> v</TT+> is returned, where <TT+>v</TT+> is the resulting value. Note+ that this value may be equal to bottom, e.g. if <TT+>c = <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Control-Monad.html#v%3Areturn"+>return</A+></TT+>+ <TT+><A HREF="Test-ChasingBottoms-IsBottom.html#v%3Abottom"+>bottom</A+></TT+></TT+>.+</LI+><LI+> If the computation does not terminate, then <TT+><A HREF="Test-ChasingBottoms-TimeOut.html#v%3ANonTermination"+>NonTermination</A+></TT+> is+ returned.+</LI+><LI+> If the computation raises an exception, then <TT+><TT+><A HREF="Test-ChasingBottoms-TimeOut.html#v%3AException"+>Exception</A+></TT+> e</TT+> is+ returned, where <TT+>e</TT+> is the exception.+</LI+></UL+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3AtimeOut%27"+></A+><B+>timeOut'</B+> :: <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Int.html#t%3AInt"+>Int</A+> -> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/System-IO.html#t%3AIO"+>IO</A+> (<A HREF="Test-ChasingBottoms-TimeOut.html#t%3AResult"+>Result</A+> a)</TD+></TR+><TR+><TD CLASS="doc"+><P+><TT+><A HREF="Test-ChasingBottoms-TimeOut.html#v%3AtimeOut%27"+>timeOut'</A+></TT+> is a variant which can be used for pure+ computations. The definition,+</P+><PRE+>+ <TT+><A HREF="Test-ChasingBottoms-TimeOut.html#v%3AtimeOut%27"+>timeOut'</A+></TT+> n = <TT+><A HREF="Test-ChasingBottoms-TimeOut.html#v%3AtimeOut"+>timeOut</A+></TT+> n . <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Control-Exception.html#v%3Aevaluate"+>evaluate</A+></TT+>+ </PRE+><P+>ensures that <TT+><TT+><A HREF="Test-ChasingBottoms-TimeOut.html#v%3AtimeOut%27"+>timeOut'</A+></TT+> 1 <TT+><A HREF="Test-ChasingBottoms-IsBottom.html#v%3Abottom"+>bottom</A+></TT+></TT+>+ usually returns <TT+><TT+><A HREF="Test-ChasingBottoms-TimeOut.html#v%3AException"+>Exception</A+></TT+> <something></TT+>. (<TT+><TT+><A HREF="Test-ChasingBottoms-TimeOut.html#v%3AtimeOut"+>timeOut</A+></TT+> 1 (<TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Control-Monad.html#v%3Areturn"+>return</A+></TT+>+ <TT+><A HREF="Test-ChasingBottoms-IsBottom.html#v%3Abottom"+>bottom</A+></TT+>)</TT+> usually returns <TT+><TT+><A HREF="Test-ChasingBottoms-TimeOut.html#v%3AValue"+>Value</A+></TT+>+ <TT+><A HREF="Test-ChasingBottoms-IsBottom.html#v%3Abottom"+>bottom</A+></TT+></TT+>; in other words, the+ computation reaches whnf almost immediately, defeating the purpose+ of the time-out.)+</P+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3AtimeOutMicro"+></A+><B+>timeOutMicro</B+> :: <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Int.html#t%3AInt"+>Int</A+> -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/System-IO.html#t%3AIO"+>IO</A+> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/System-IO.html#t%3AIO"+>IO</A+> (<A HREF="Test-ChasingBottoms-TimeOut.html#t%3AResult"+>Result</A+> a)</TD+></TR+><TR+><TD CLASS="doc"+><TT+><A HREF="Test-ChasingBottoms-TimeOut.html#v%3AtimeOutMicro"+>timeOutMicro</A+></TT+> takes a delay in microseconds. Note that the+ resolution is not necessarily very high (the last time I checked it+ was 0.02 seconds when using the standard runtime system settings+ for GHC).+</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+><A NAME="v%3AtimeOutMicro%27"+></A+><B+>timeOutMicro'</B+> :: <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Data-Int.html#t%3AInt"+>Int</A+> -> a -> <A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/System-IO.html#t%3AIO"+>IO</A+> (<A HREF="Test-ChasingBottoms-TimeOut.html#t%3AResult"+>Result</A+> a)</TD+></TR+><TR+><TD CLASS="doc"+><P+><TT+><A HREF="Test-ChasingBottoms-TimeOut.html#v%3AtimeOutMicro%27"+>timeOutMicro'</A+></TT+> is the equivalent variant of <TT+><A HREF="Test-ChasingBottoms-TimeOut.html#v%3AtimeOutMicro"+>timeOutMicro</A+></TT+>:+</P+><PRE+>+ <TT+><A HREF="Test-ChasingBottoms-TimeOut.html#v%3AtimeOutMicro%27"+>timeOutMicro'</A+></TT+> n = <TT+><A HREF="Test-ChasingBottoms-TimeOut.html#v%3AtimeOutMicro"+>timeOutMicro</A+></TT+> n . <TT+><A HREF="http://www.haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/Control-Exception.html#v%3Aevaluate"+>evaluate</A+></TT+>+ </PRE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="botbar"+>Produced by <A HREF="http://www.haskell.org/haddock/"+>Haddock</A+> version 0.7</TD+></TR+></TABLE+></BODY+></HTML+>
+ docs/Test-ChasingBottoms.html view
@@ -0,0 +1,187 @@+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">+<!--Rendered using the Haskell Html Library v0.2-->+<HTML+><HEAD+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"+><TITLE+>Test.ChasingBottoms</TITLE+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"+><SCRIPT SRC="haddock.js" TYPE="text/javascript"+></SCRIPT+></HEAD+><BODY+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="topbar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "+></TD+><TD CLASS="title"+>Chasing Bottoms</TD+><TD CLASS="topbut"+><A HREF="index.html"+>Contents</A+></TD+><TD CLASS="topbut"+><A HREF="doc-index.html"+>Index</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="modulebar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><FONT SIZE="6"+>Test.ChasingBottoms</FONT+></TD+><TD ALIGN="right"+><TABLE CLASS="narrow" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="infohead"+>Portability</TD+><TD CLASS="infoval"+>non-portable (GHC-specific)</TD+></TR+><TR+><TD CLASS="infohead"+>Stability</TD+><TD CLASS="infoval"+>experimental</TD+></TR+><TR+><TD CLASS="infohead"+>Maintainer</TD+><TD CLASS="infoval"+>http://www.cs.chalmers.se/~nad/</TD+></TR+></TABLE+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+></TABLE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="section1"+>Description</TD+></TR+><TR+><TD CLASS="doc"+>This module just re-exports all the other modules.+</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="section1"+>Documentation</TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+>module <A HREF="Test-ChasingBottoms-Approx.html"+>Test.ChasingBottoms.Approx</A+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+>module <A HREF="Test-ChasingBottoms-ApproxShow.html"+>Test.ChasingBottoms.ApproxShow</A+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+>module <A HREF="Test-ChasingBottoms-ContinuousFunctions.html"+>Test.ChasingBottoms.ContinuousFunctions</A+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+>module <A HREF="Test-ChasingBottoms-IsBottom.html"+>Test.ChasingBottoms.IsBottom</A+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+>module <A HREF="Test-ChasingBottoms-Nat.html"+>Test.ChasingBottoms.Nat</A+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+>module <A HREF="Test-ChasingBottoms-SemanticOrd.html"+>Test.ChasingBottoms.SemanticOrd</A+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="decl"+>module <A HREF="Test-ChasingBottoms-TimeOut.html"+>Test.ChasingBottoms.TimeOut</A+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="botbar"+>Produced by <A HREF="http://www.haskell.org/haddock/"+>Haddock</A+> version 0.7</TD+></TR+></TABLE+></BODY+></HTML+>
+ docs/doc-index-47.html view
@@ -0,0 +1,154 @@+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">+<!--Rendered using the Haskell Html Library v0.2-->+<HTML+><HEAD+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"+><TITLE+>Chasing Bottoms (Index)</TITLE+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"+></HEAD+><BODY+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="topbar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "+></TD+><TD CLASS="title"+>Chasing Bottoms</TD+><TD CLASS="topbut"+><A HREF="index.html"+>Contents</A+></TD+><TD CLASS="topbut"+><A HREF="doc-index.html"+>Index</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD+><A HREF="doc-index-A.html"+>A</A+></TD+><TD+><A HREF="doc-index-B.html"+>B</A+></TD+><TD+><A HREF="doc-index-C.html"+>C</A+></TD+><TD+><A HREF="doc-index-E.html"+>E</A+></TD+><TD+><A HREF="doc-index-F.html"+>F</A+></TD+><TD+><A HREF="doc-index-G.html"+>G</A+></TD+><TD+><A HREF="doc-index-I.html"+>I</A+></TD+><TD+><A HREF="doc-index-L.html"+>L</A+></TD+><TD+><A HREF="doc-index-M.html"+>M</A+></TD+><TD+><A HREF="doc-index-N.html"+>N</A+></TD+><TD+><A HREF="doc-index-O.html"+>O</A+></TD+><TD+><A HREF="doc-index-P.html"+>P</A+></TD+><TD+><A HREF="doc-index-R.html"+>R</A+></TD+><TD+><A HREF="doc-index-S.html"+>S</A+></TD+><TD+><A HREF="doc-index-T.html"+>T</A+></TD+><TD+><A HREF="doc-index-V.html"+>V</A+></TD+><TD+><A HREF="doc-index-47.html"+>/</A+></TD+><TD+><A HREF="doc-index-60.html"+><</A+></TD+><TD+><A HREF="doc-index-61.html"+>=</A+></TD+><TD+><A HREF="doc-index-62.html"+>></A+></TD+><TD+><A HREF="doc-index-92.html"+>\</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="section1"+>Index (/)</TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD CLASS="indexentry"+>/=!</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-SemanticOrd.html#v%3A%2F%3D%21"+>Test.ChasingBottoms.SemanticOrd</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>/\!</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-SemanticOrd.html#v%3A%2F%5C%21"+>Test.ChasingBottoms.SemanticOrd</A+>, Test.ChasingBottoms</TD+></TR+></TABLE+></TD+></TR+></TABLE+></BODY+></HTML+>
+ docs/doc-index-60.html view
@@ -0,0 +1,154 @@+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">+<!--Rendered using the Haskell Html Library v0.2-->+<HTML+><HEAD+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"+><TITLE+>Chasing Bottoms (Index)</TITLE+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"+></HEAD+><BODY+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="topbar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "+></TD+><TD CLASS="title"+>Chasing Bottoms</TD+><TD CLASS="topbut"+><A HREF="index.html"+>Contents</A+></TD+><TD CLASS="topbut"+><A HREF="doc-index.html"+>Index</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD+><A HREF="doc-index-A.html"+>A</A+></TD+><TD+><A HREF="doc-index-B.html"+>B</A+></TD+><TD+><A HREF="doc-index-C.html"+>C</A+></TD+><TD+><A HREF="doc-index-E.html"+>E</A+></TD+><TD+><A HREF="doc-index-F.html"+>F</A+></TD+><TD+><A HREF="doc-index-G.html"+>G</A+></TD+><TD+><A HREF="doc-index-I.html"+>I</A+></TD+><TD+><A HREF="doc-index-L.html"+>L</A+></TD+><TD+><A HREF="doc-index-M.html"+>M</A+></TD+><TD+><A HREF="doc-index-N.html"+>N</A+></TD+><TD+><A HREF="doc-index-O.html"+>O</A+></TD+><TD+><A HREF="doc-index-P.html"+>P</A+></TD+><TD+><A HREF="doc-index-R.html"+>R</A+></TD+><TD+><A HREF="doc-index-S.html"+>S</A+></TD+><TD+><A HREF="doc-index-T.html"+>T</A+></TD+><TD+><A HREF="doc-index-V.html"+>V</A+></TD+><TD+><A HREF="doc-index-47.html"+>/</A+></TD+><TD+><A HREF="doc-index-60.html"+><</A+></TD+><TD+><A HREF="doc-index-61.html"+>=</A+></TD+><TD+><A HREF="doc-index-62.html"+>></A+></TD+><TD+><A HREF="doc-index-92.html"+>\</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="section1"+>Index (<)</TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD CLASS="indexentry"+><!</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-SemanticOrd.html#v%3A%3C%21"+>Test.ChasingBottoms.SemanticOrd</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+><=!</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-SemanticOrd.html#v%3A%3C%3D%21"+>Test.ChasingBottoms.SemanticOrd</A+>, Test.ChasingBottoms</TD+></TR+></TABLE+></TD+></TR+></TABLE+></BODY+></HTML+>
+ docs/doc-index-61.html view
@@ -0,0 +1,146 @@+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">+<!--Rendered using the Haskell Html Library v0.2-->+<HTML+><HEAD+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"+><TITLE+>Chasing Bottoms (Index)</TITLE+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"+></HEAD+><BODY+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="topbar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "+></TD+><TD CLASS="title"+>Chasing Bottoms</TD+><TD CLASS="topbut"+><A HREF="index.html"+>Contents</A+></TD+><TD CLASS="topbut"+><A HREF="doc-index.html"+>Index</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD+><A HREF="doc-index-A.html"+>A</A+></TD+><TD+><A HREF="doc-index-B.html"+>B</A+></TD+><TD+><A HREF="doc-index-C.html"+>C</A+></TD+><TD+><A HREF="doc-index-E.html"+>E</A+></TD+><TD+><A HREF="doc-index-F.html"+>F</A+></TD+><TD+><A HREF="doc-index-G.html"+>G</A+></TD+><TD+><A HREF="doc-index-I.html"+>I</A+></TD+><TD+><A HREF="doc-index-L.html"+>L</A+></TD+><TD+><A HREF="doc-index-M.html"+>M</A+></TD+><TD+><A HREF="doc-index-N.html"+>N</A+></TD+><TD+><A HREF="doc-index-O.html"+>O</A+></TD+><TD+><A HREF="doc-index-P.html"+>P</A+></TD+><TD+><A HREF="doc-index-R.html"+>R</A+></TD+><TD+><A HREF="doc-index-S.html"+>S</A+></TD+><TD+><A HREF="doc-index-T.html"+>T</A+></TD+><TD+><A HREF="doc-index-V.html"+>V</A+></TD+><TD+><A HREF="doc-index-47.html"+>/</A+></TD+><TD+><A HREF="doc-index-60.html"+><</A+></TD+><TD+><A HREF="doc-index-61.html"+>=</A+></TD+><TD+><A HREF="doc-index-62.html"+>></A+></TD+><TD+><A HREF="doc-index-92.html"+>\</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="section1"+>Index (=)</TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD CLASS="indexentry"+>==!</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-SemanticOrd.html#v%3A%3D%3D%21"+>Test.ChasingBottoms.SemanticOrd</A+>, Test.ChasingBottoms</TD+></TR+></TABLE+></TD+></TR+></TABLE+></BODY+></HTML+>
+ docs/doc-index-62.html view
@@ -0,0 +1,154 @@+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">+<!--Rendered using the Haskell Html Library v0.2-->+<HTML+><HEAD+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"+><TITLE+>Chasing Bottoms (Index)</TITLE+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"+></HEAD+><BODY+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="topbar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "+></TD+><TD CLASS="title"+>Chasing Bottoms</TD+><TD CLASS="topbut"+><A HREF="index.html"+>Contents</A+></TD+><TD CLASS="topbut"+><A HREF="doc-index.html"+>Index</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD+><A HREF="doc-index-A.html"+>A</A+></TD+><TD+><A HREF="doc-index-B.html"+>B</A+></TD+><TD+><A HREF="doc-index-C.html"+>C</A+></TD+><TD+><A HREF="doc-index-E.html"+>E</A+></TD+><TD+><A HREF="doc-index-F.html"+>F</A+></TD+><TD+><A HREF="doc-index-G.html"+>G</A+></TD+><TD+><A HREF="doc-index-I.html"+>I</A+></TD+><TD+><A HREF="doc-index-L.html"+>L</A+></TD+><TD+><A HREF="doc-index-M.html"+>M</A+></TD+><TD+><A HREF="doc-index-N.html"+>N</A+></TD+><TD+><A HREF="doc-index-O.html"+>O</A+></TD+><TD+><A HREF="doc-index-P.html"+>P</A+></TD+><TD+><A HREF="doc-index-R.html"+>R</A+></TD+><TD+><A HREF="doc-index-S.html"+>S</A+></TD+><TD+><A HREF="doc-index-T.html"+>T</A+></TD+><TD+><A HREF="doc-index-V.html"+>V</A+></TD+><TD+><A HREF="doc-index-47.html"+>/</A+></TD+><TD+><A HREF="doc-index-60.html"+><</A+></TD+><TD+><A HREF="doc-index-61.html"+>=</A+></TD+><TD+><A HREF="doc-index-62.html"+>></A+></TD+><TD+><A HREF="doc-index-92.html"+>\</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="section1"+>Index (>)</TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD CLASS="indexentry"+>>!</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-SemanticOrd.html#v%3A%3E%21"+>Test.ChasingBottoms.SemanticOrd</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>>=!</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-SemanticOrd.html#v%3A%3E%3D%21"+>Test.ChasingBottoms.SemanticOrd</A+>, Test.ChasingBottoms</TD+></TR+></TABLE+></TD+></TR+></TABLE+></BODY+></HTML+>
+ docs/doc-index-92.html view
@@ -0,0 +1,146 @@+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">+<!--Rendered using the Haskell Html Library v0.2-->+<HTML+><HEAD+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"+><TITLE+>Chasing Bottoms (Index)</TITLE+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"+></HEAD+><BODY+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="topbar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "+></TD+><TD CLASS="title"+>Chasing Bottoms</TD+><TD CLASS="topbut"+><A HREF="index.html"+>Contents</A+></TD+><TD CLASS="topbut"+><A HREF="doc-index.html"+>Index</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD+><A HREF="doc-index-A.html"+>A</A+></TD+><TD+><A HREF="doc-index-B.html"+>B</A+></TD+><TD+><A HREF="doc-index-C.html"+>C</A+></TD+><TD+><A HREF="doc-index-E.html"+>E</A+></TD+><TD+><A HREF="doc-index-F.html"+>F</A+></TD+><TD+><A HREF="doc-index-G.html"+>G</A+></TD+><TD+><A HREF="doc-index-I.html"+>I</A+></TD+><TD+><A HREF="doc-index-L.html"+>L</A+></TD+><TD+><A HREF="doc-index-M.html"+>M</A+></TD+><TD+><A HREF="doc-index-N.html"+>N</A+></TD+><TD+><A HREF="doc-index-O.html"+>O</A+></TD+><TD+><A HREF="doc-index-P.html"+>P</A+></TD+><TD+><A HREF="doc-index-R.html"+>R</A+></TD+><TD+><A HREF="doc-index-S.html"+>S</A+></TD+><TD+><A HREF="doc-index-T.html"+>T</A+></TD+><TD+><A HREF="doc-index-V.html"+>V</A+></TD+><TD+><A HREF="doc-index-47.html"+>/</A+></TD+><TD+><A HREF="doc-index-60.html"+><</A+></TD+><TD+><A HREF="doc-index-61.html"+>=</A+></TD+><TD+><A HREF="doc-index-62.html"+>></A+></TD+><TD+><A HREF="doc-index-92.html"+>\</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="section1"+>Index (\)</TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD CLASS="indexentry"+>\/!</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-SemanticOrd.html#v%3A%5C%2F%21"+>Test.ChasingBottoms.SemanticOrd</A+>, Test.ChasingBottoms</TD+></TR+></TABLE+></TD+></TR+></TABLE+></BODY+></HTML+>
+ docs/doc-index-A.html view
@@ -0,0 +1,218 @@+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">+<!--Rendered using the Haskell Html Library v0.2-->+<HTML+><HEAD+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"+><TITLE+>Chasing Bottoms (Index)</TITLE+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"+></HEAD+><BODY+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="topbar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "+></TD+><TD CLASS="title"+>Chasing Bottoms</TD+><TD CLASS="topbut"+><A HREF="index.html"+>Contents</A+></TD+><TD CLASS="topbut"+><A HREF="doc-index.html"+>Index</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD+><A HREF="doc-index-A.html"+>A</A+></TD+><TD+><A HREF="doc-index-B.html"+>B</A+></TD+><TD+><A HREF="doc-index-C.html"+>C</A+></TD+><TD+><A HREF="doc-index-E.html"+>E</A+></TD+><TD+><A HREF="doc-index-F.html"+>F</A+></TD+><TD+><A HREF="doc-index-G.html"+>G</A+></TD+><TD+><A HREF="doc-index-I.html"+>I</A+></TD+><TD+><A HREF="doc-index-L.html"+>L</A+></TD+><TD+><A HREF="doc-index-M.html"+>M</A+></TD+><TD+><A HREF="doc-index-N.html"+>N</A+></TD+><TD+><A HREF="doc-index-O.html"+>O</A+></TD+><TD+><A HREF="doc-index-P.html"+>P</A+></TD+><TD+><A HREF="doc-index-R.html"+>R</A+></TD+><TD+><A HREF="doc-index-S.html"+>S</A+></TD+><TD+><A HREF="doc-index-T.html"+>T</A+></TD+><TD+><A HREF="doc-index-V.html"+>V</A+></TD+><TD+><A HREF="doc-index-47.html"+>/</A+></TD+><TD+><A HREF="doc-index-60.html"+><</A+></TD+><TD+><A HREF="doc-index-61.html"+>=</A+></TD+><TD+><A HREF="doc-index-62.html"+>></A+></TD+><TD+><A HREF="doc-index-92.html"+>\</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="section1"+>Index (A)</TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD CLASS="indexentry"+>Approx</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-Approx.html#t%3AApprox"+>Test.ChasingBottoms.Approx</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>ApproxShow</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-ApproxShow.html#t%3AApproxShow"+>Test.ChasingBottoms.ApproxShow</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>apply</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#v%3Aapply"+>Test.ChasingBottoms.ContinuousFunctions</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>approx</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-Approx.html#v%3Aapprox"+>Test.ChasingBottoms.Approx</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>approxAll</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-Approx.html#v%3AapproxAll"+>Test.ChasingBottoms.Approx</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>approxDepth</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-SemanticOrd.html#v%3AapproxDepth"+>Test.ChasingBottoms.SemanticOrd</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>approxShow</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-ApproxShow.html#v%3AapproxShow"+>Test.ChasingBottoms.ApproxShow</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>approxShows</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-ApproxShow.html#v%3AapproxShows"+>Test.ChasingBottoms.ApproxShow</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>approxShowsPrec</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-ApproxShow.html#v%3AapproxShowsPrec"+>Test.ChasingBottoms.ApproxShow</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>arbitrary'</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#v%3Aarbitrary%27"+>Test.ChasingBottoms.ContinuousFunctions</A+>, Test.ChasingBottoms</TD+></TR+></TABLE+></TD+></TR+></TABLE+></BODY+></HTML+>
+ docs/doc-index-B.html view
@@ -0,0 +1,146 @@+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">+<!--Rendered using the Haskell Html Library v0.2-->+<HTML+><HEAD+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"+><TITLE+>Chasing Bottoms (Index)</TITLE+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"+></HEAD+><BODY+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="topbar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "+></TD+><TD CLASS="title"+>Chasing Bottoms</TD+><TD CLASS="topbut"+><A HREF="index.html"+>Contents</A+></TD+><TD CLASS="topbut"+><A HREF="doc-index.html"+>Index</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD+><A HREF="doc-index-A.html"+>A</A+></TD+><TD+><A HREF="doc-index-B.html"+>B</A+></TD+><TD+><A HREF="doc-index-C.html"+>C</A+></TD+><TD+><A HREF="doc-index-E.html"+>E</A+></TD+><TD+><A HREF="doc-index-F.html"+>F</A+></TD+><TD+><A HREF="doc-index-G.html"+>G</A+></TD+><TD+><A HREF="doc-index-I.html"+>I</A+></TD+><TD+><A HREF="doc-index-L.html"+>L</A+></TD+><TD+><A HREF="doc-index-M.html"+>M</A+></TD+><TD+><A HREF="doc-index-N.html"+>N</A+></TD+><TD+><A HREF="doc-index-O.html"+>O</A+></TD+><TD+><A HREF="doc-index-P.html"+>P</A+></TD+><TD+><A HREF="doc-index-R.html"+>R</A+></TD+><TD+><A HREF="doc-index-S.html"+>S</A+></TD+><TD+><A HREF="doc-index-T.html"+>T</A+></TD+><TD+><A HREF="doc-index-V.html"+>V</A+></TD+><TD+><A HREF="doc-index-47.html"+>/</A+></TD+><TD+><A HREF="doc-index-60.html"+><</A+></TD+><TD+><A HREF="doc-index-61.html"+>=</A+></TD+><TD+><A HREF="doc-index-62.html"+>></A+></TD+><TD+><A HREF="doc-index-92.html"+>\</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="section1"+>Index (B)</TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD CLASS="indexentry"+>bottom</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-IsBottom.html#v%3Abottom"+>Test.ChasingBottoms.IsBottom</A+>, Test.ChasingBottoms</TD+></TR+></TABLE+></TD+></TR+></TABLE+></BODY+></HTML+>
+ docs/doc-index-C.html view
@@ -0,0 +1,146 @@+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">+<!--Rendered using the Haskell Html Library v0.2-->+<HTML+><HEAD+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"+><TITLE+>Chasing Bottoms (Index)</TITLE+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"+></HEAD+><BODY+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="topbar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "+></TD+><TD CLASS="title"+>Chasing Bottoms</TD+><TD CLASS="topbut"+><A HREF="index.html"+>Contents</A+></TD+><TD CLASS="topbut"+><A HREF="doc-index.html"+>Index</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD+><A HREF="doc-index-A.html"+>A</A+></TD+><TD+><A HREF="doc-index-B.html"+>B</A+></TD+><TD+><A HREF="doc-index-C.html"+>C</A+></TD+><TD+><A HREF="doc-index-E.html"+>E</A+></TD+><TD+><A HREF="doc-index-F.html"+>F</A+></TD+><TD+><A HREF="doc-index-G.html"+>G</A+></TD+><TD+><A HREF="doc-index-I.html"+>I</A+></TD+><TD+><A HREF="doc-index-L.html"+>L</A+></TD+><TD+><A HREF="doc-index-M.html"+>M</A+></TD+><TD+><A HREF="doc-index-N.html"+>N</A+></TD+><TD+><A HREF="doc-index-O.html"+>O</A+></TD+><TD+><A HREF="doc-index-P.html"+>P</A+></TD+><TD+><A HREF="doc-index-R.html"+>R</A+></TD+><TD+><A HREF="doc-index-S.html"+>S</A+></TD+><TD+><A HREF="doc-index-T.html"+>T</A+></TD+><TD+><A HREF="doc-index-V.html"+>V</A+></TD+><TD+><A HREF="doc-index-47.html"+>/</A+></TD+><TD+><A HREF="doc-index-60.html"+><</A+></TD+><TD+><A HREF="doc-index-61.html"+>=</A+></TD+><TD+><A HREF="doc-index-62.html"+>></A+></TD+><TD+><A HREF="doc-index-92.html"+>\</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="section1"+>Index (C)</TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD CLASS="indexentry"+>choose'</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#v%3Achoose%27"+>Test.ChasingBottoms.ContinuousFunctions</A+>, Test.ChasingBottoms</TD+></TR+></TABLE+></TD+></TR+></TABLE+></BODY+></HTML+>
+ docs/doc-index-E.html view
@@ -0,0 +1,154 @@+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">+<!--Rendered using the Haskell Html Library v0.2-->+<HTML+><HEAD+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"+><TITLE+>Chasing Bottoms (Index)</TITLE+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"+></HEAD+><BODY+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="topbar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "+></TD+><TD CLASS="title"+>Chasing Bottoms</TD+><TD CLASS="topbut"+><A HREF="index.html"+>Contents</A+></TD+><TD CLASS="topbut"+><A HREF="doc-index.html"+>Index</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD+><A HREF="doc-index-A.html"+>A</A+></TD+><TD+><A HREF="doc-index-B.html"+>B</A+></TD+><TD+><A HREF="doc-index-C.html"+>C</A+></TD+><TD+><A HREF="doc-index-E.html"+>E</A+></TD+><TD+><A HREF="doc-index-F.html"+>F</A+></TD+><TD+><A HREF="doc-index-G.html"+>G</A+></TD+><TD+><A HREF="doc-index-I.html"+>I</A+></TD+><TD+><A HREF="doc-index-L.html"+>L</A+></TD+><TD+><A HREF="doc-index-M.html"+>M</A+></TD+><TD+><A HREF="doc-index-N.html"+>N</A+></TD+><TD+><A HREF="doc-index-O.html"+>O</A+></TD+><TD+><A HREF="doc-index-P.html"+>P</A+></TD+><TD+><A HREF="doc-index-R.html"+>R</A+></TD+><TD+><A HREF="doc-index-S.html"+>S</A+></TD+><TD+><A HREF="doc-index-T.html"+>T</A+></TD+><TD+><A HREF="doc-index-V.html"+>V</A+></TD+><TD+><A HREF="doc-index-47.html"+>/</A+></TD+><TD+><A HREF="doc-index-60.html"+><</A+></TD+><TD+><A HREF="doc-index-61.html"+>=</A+></TD+><TD+><A HREF="doc-index-62.html"+>></A+></TD+><TD+><A HREF="doc-index-92.html"+>\</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="section1"+>Index (E)</TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD CLASS="indexentry"+>Exception</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-TimeOut.html#v%3AException"+>Test.ChasingBottoms.TimeOut</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>elements'</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#v%3Aelements%27"+>Test.ChasingBottoms.ContinuousFunctions</A+>, Test.ChasingBottoms</TD+></TR+></TABLE+></TD+></TR+></TABLE+></BODY+></HTML+>
+ docs/doc-index-F.html view
@@ -0,0 +1,194 @@+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">+<!--Rendered using the Haskell Html Library v0.2-->+<HTML+><HEAD+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"+><TITLE+>Chasing Bottoms (Index)</TITLE+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"+></HEAD+><BODY+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="topbar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "+></TD+><TD CLASS="title"+>Chasing Bottoms</TD+><TD CLASS="topbut"+><A HREF="index.html"+>Contents</A+></TD+><TD CLASS="topbut"+><A HREF="doc-index.html"+>Index</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD+><A HREF="doc-index-A.html"+>A</A+></TD+><TD+><A HREF="doc-index-B.html"+>B</A+></TD+><TD+><A HREF="doc-index-C.html"+>C</A+></TD+><TD+><A HREF="doc-index-E.html"+>E</A+></TD+><TD+><A HREF="doc-index-F.html"+>F</A+></TD+><TD+><A HREF="doc-index-G.html"+>G</A+></TD+><TD+><A HREF="doc-index-I.html"+>I</A+></TD+><TD+><A HREF="doc-index-L.html"+>L</A+></TD+><TD+><A HREF="doc-index-M.html"+>M</A+></TD+><TD+><A HREF="doc-index-N.html"+>N</A+></TD+><TD+><A HREF="doc-index-O.html"+>O</A+></TD+><TD+><A HREF="doc-index-P.html"+>P</A+></TD+><TD+><A HREF="doc-index-R.html"+>R</A+></TD+><TD+><A HREF="doc-index-S.html"+>S</A+></TD+><TD+><A HREF="doc-index-T.html"+>T</A+></TD+><TD+><A HREF="doc-index-V.html"+>V</A+></TD+><TD+><A HREF="doc-index-47.html"+>/</A+></TD+><TD+><A HREF="doc-index-60.html"+><</A+></TD+><TD+><A HREF="doc-index-61.html"+>=</A+></TD+><TD+><A HREF="doc-index-62.html"+>></A+></TD+><TD+><A HREF="doc-index-92.html"+>\</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="section1"+>Index (F)</TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD CLASS="indexentry"+>finiteListOf</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#v%3AfiniteListOf"+>Test.ChasingBottoms.ContinuousFunctions</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>flat</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#v%3Aflat"+>Test.ChasingBottoms.ContinuousFunctions</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>foldN</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-Nat.html#v%3AfoldN"+>Test.ChasingBottoms.Nat</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>frequency'</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#v%3Afrequency%27"+>Test.ChasingBottoms.ContinuousFunctions</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>fromSucc</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-Nat.html#v%3AfromSucc"+>Test.ChasingBottoms.Nat</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>function</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#v%3Afunction"+>Test.ChasingBottoms.ContinuousFunctions</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>functionTo</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#v%3AfunctionTo"+>Test.ChasingBottoms.ContinuousFunctions</A+>, Test.ChasingBottoms</TD+></TR+></TABLE+></TD+></TR+></TABLE+></BODY+></HTML+>
+ docs/doc-index-G.html view
@@ -0,0 +1,146 @@+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">+<!--Rendered using the Haskell Html Library v0.2-->+<HTML+><HEAD+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"+><TITLE+>Chasing Bottoms (Index)</TITLE+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"+></HEAD+><BODY+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="topbar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "+></TD+><TD CLASS="title"+>Chasing Bottoms</TD+><TD CLASS="topbut"+><A HREF="index.html"+>Contents</A+></TD+><TD CLASS="topbut"+><A HREF="doc-index.html"+>Index</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD+><A HREF="doc-index-A.html"+>A</A+></TD+><TD+><A HREF="doc-index-B.html"+>B</A+></TD+><TD+><A HREF="doc-index-C.html"+>C</A+></TD+><TD+><A HREF="doc-index-E.html"+>E</A+></TD+><TD+><A HREF="doc-index-F.html"+>F</A+></TD+><TD+><A HREF="doc-index-G.html"+>G</A+></TD+><TD+><A HREF="doc-index-I.html"+>I</A+></TD+><TD+><A HREF="doc-index-L.html"+>L</A+></TD+><TD+><A HREF="doc-index-M.html"+>M</A+></TD+><TD+><A HREF="doc-index-N.html"+>N</A+></TD+><TD+><A HREF="doc-index-O.html"+>O</A+></TD+><TD+><A HREF="doc-index-P.html"+>P</A+></TD+><TD+><A HREF="doc-index-R.html"+>R</A+></TD+><TD+><A HREF="doc-index-S.html"+>S</A+></TD+><TD+><A HREF="doc-index-T.html"+>T</A+></TD+><TD+><A HREF="doc-index-V.html"+>V</A+></TD+><TD+><A HREF="doc-index-47.html"+>/</A+></TD+><TD+><A HREF="doc-index-60.html"+><</A+></TD+><TD+><A HREF="doc-index-61.html"+>=</A+></TD+><TD+><A HREF="doc-index-62.html"+>></A+></TD+><TD+><A HREF="doc-index-92.html"+>\</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="section1"+>Index (G)</TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD CLASS="indexentry"+>GenTransformer</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AGenTransformer"+>Test.ChasingBottoms.ContinuousFunctions</A+>, Test.ChasingBottoms</TD+></TR+></TABLE+></TD+></TR+></TABLE+></BODY+></HTML+>
+ docs/doc-index-I.html view
@@ -0,0 +1,170 @@+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">+<!--Rendered using the Haskell Html Library v0.2-->+<HTML+><HEAD+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"+><TITLE+>Chasing Bottoms (Index)</TITLE+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"+></HEAD+><BODY+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="topbar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "+></TD+><TD CLASS="title"+>Chasing Bottoms</TD+><TD CLASS="topbut"+><A HREF="index.html"+>Contents</A+></TD+><TD CLASS="topbut"+><A HREF="doc-index.html"+>Index</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD+><A HREF="doc-index-A.html"+>A</A+></TD+><TD+><A HREF="doc-index-B.html"+>B</A+></TD+><TD+><A HREF="doc-index-C.html"+>C</A+></TD+><TD+><A HREF="doc-index-E.html"+>E</A+></TD+><TD+><A HREF="doc-index-F.html"+>F</A+></TD+><TD+><A HREF="doc-index-G.html"+>G</A+></TD+><TD+><A HREF="doc-index-I.html"+>I</A+></TD+><TD+><A HREF="doc-index-L.html"+>L</A+></TD+><TD+><A HREF="doc-index-M.html"+>M</A+></TD+><TD+><A HREF="doc-index-N.html"+>N</A+></TD+><TD+><A HREF="doc-index-O.html"+>O</A+></TD+><TD+><A HREF="doc-index-P.html"+>P</A+></TD+><TD+><A HREF="doc-index-R.html"+>R</A+></TD+><TD+><A HREF="doc-index-S.html"+>S</A+></TD+><TD+><A HREF="doc-index-T.html"+>T</A+></TD+><TD+><A HREF="doc-index-V.html"+>V</A+></TD+><TD+><A HREF="doc-index-47.html"+>/</A+></TD+><TD+><A HREF="doc-index-60.html"+><</A+></TD+><TD+><A HREF="doc-index-61.html"+>=</A+></TD+><TD+><A HREF="doc-index-62.html"+>></A+></TD+><TD+><A HREF="doc-index-92.html"+>\</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="section1"+>Index (I)</TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD CLASS="indexentry"+>infiniteListOf</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#v%3AinfiniteListOf"+>Test.ChasingBottoms.ContinuousFunctions</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>isBottom</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-IsBottom.html#v%3AisBottom"+>Test.ChasingBottoms.IsBottom</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>isBottomTimeOut</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-IsBottom.html#v%3AisBottomTimeOut"+>Test.ChasingBottoms.IsBottom</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>isSucc</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-Nat.html#v%3AisSucc"+>Test.ChasingBottoms.Nat</A+>, Test.ChasingBottoms</TD+></TR+></TABLE+></TD+></TR+></TABLE+></BODY+></HTML+>
+ docs/doc-index-L.html view
@@ -0,0 +1,154 @@+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">+<!--Rendered using the Haskell Html Library v0.2-->+<HTML+><HEAD+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"+><TITLE+>Chasing Bottoms (Index)</TITLE+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"+></HEAD+><BODY+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="topbar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "+></TD+><TD CLASS="title"+>Chasing Bottoms</TD+><TD CLASS="topbut"+><A HREF="index.html"+>Contents</A+></TD+><TD CLASS="topbut"+><A HREF="doc-index.html"+>Index</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD+><A HREF="doc-index-A.html"+>A</A+></TD+><TD+><A HREF="doc-index-B.html"+>B</A+></TD+><TD+><A HREF="doc-index-C.html"+>C</A+></TD+><TD+><A HREF="doc-index-E.html"+>E</A+></TD+><TD+><A HREF="doc-index-F.html"+>F</A+></TD+><TD+><A HREF="doc-index-G.html"+>G</A+></TD+><TD+><A HREF="doc-index-I.html"+>I</A+></TD+><TD+><A HREF="doc-index-L.html"+>L</A+></TD+><TD+><A HREF="doc-index-M.html"+>M</A+></TD+><TD+><A HREF="doc-index-N.html"+>N</A+></TD+><TD+><A HREF="doc-index-O.html"+>O</A+></TD+><TD+><A HREF="doc-index-P.html"+>P</A+></TD+><TD+><A HREF="doc-index-R.html"+>R</A+></TD+><TD+><A HREF="doc-index-S.html"+>S</A+></TD+><TD+><A HREF="doc-index-T.html"+>T</A+></TD+><TD+><A HREF="doc-index-V.html"+>V</A+></TD+><TD+><A HREF="doc-index-47.html"+>/</A+></TD+><TD+><A HREF="doc-index-60.html"+><</A+></TD+><TD+><A HREF="doc-index-61.html"+>=</A+></TD+><TD+><A HREF="doc-index-62.html"+>></A+></TD+><TD+><A HREF="doc-index-92.html"+>\</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="section1"+>Index (L)</TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD CLASS="indexentry"+>lift'</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#v%3Alift%27"+>Test.ChasingBottoms.ContinuousFunctions</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>listOf</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#v%3AlistOf"+>Test.ChasingBottoms.ContinuousFunctions</A+>, Test.ChasingBottoms</TD+></TR+></TABLE+></TD+></TR+></TABLE+></BODY+></HTML+>
+ docs/doc-index-M.html view
@@ -0,0 +1,170 @@+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">+<!--Rendered using the Haskell Html Library v0.2-->+<HTML+><HEAD+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"+><TITLE+>Chasing Bottoms (Index)</TITLE+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"+></HEAD+><BODY+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="topbar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "+></TD+><TD CLASS="title"+>Chasing Bottoms</TD+><TD CLASS="topbut"+><A HREF="index.html"+>Contents</A+></TD+><TD CLASS="topbut"+><A HREF="doc-index.html"+>Index</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD+><A HREF="doc-index-A.html"+>A</A+></TD+><TD+><A HREF="doc-index-B.html"+>B</A+></TD+><TD+><A HREF="doc-index-C.html"+>C</A+></TD+><TD+><A HREF="doc-index-E.html"+>E</A+></TD+><TD+><A HREF="doc-index-F.html"+>F</A+></TD+><TD+><A HREF="doc-index-G.html"+>G</A+></TD+><TD+><A HREF="doc-index-I.html"+>I</A+></TD+><TD+><A HREF="doc-index-L.html"+>L</A+></TD+><TD+><A HREF="doc-index-M.html"+>M</A+></TD+><TD+><A HREF="doc-index-N.html"+>N</A+></TD+><TD+><A HREF="doc-index-O.html"+>O</A+></TD+><TD+><A HREF="doc-index-P.html"+>P</A+></TD+><TD+><A HREF="doc-index-R.html"+>R</A+></TD+><TD+><A HREF="doc-index-S.html"+>S</A+></TD+><TD+><A HREF="doc-index-T.html"+>T</A+></TD+><TD+><A HREF="doc-index-V.html"+>V</A+></TD+><TD+><A HREF="doc-index-47.html"+>/</A+></TD+><TD+><A HREF="doc-index-60.html"+><</A+></TD+><TD+><A HREF="doc-index-61.html"+>=</A+></TD+><TD+><A HREF="doc-index-62.html"+>></A+></TD+><TD+><A HREF="doc-index-92.html"+>\</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="section1"+>Index (M)</TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD CLASS="indexentry"+>MakePM</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakePM"+>Test.ChasingBottoms.ContinuousFunctions</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>MakeResult</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3AMakeResult"+>Test.ChasingBottoms.ContinuousFunctions</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>match</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#v%3Amatch"+>Test.ChasingBottoms.ContinuousFunctions</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>more</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#v%3Amore"+>Test.ChasingBottoms.ContinuousFunctions</A+>, Test.ChasingBottoms</TD+></TR+></TABLE+></TD+></TR+></TABLE+></BODY+></HTML+>
+ docs/doc-index-N.html view
@@ -0,0 +1,178 @@+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">+<!--Rendered using the Haskell Html Library v0.2-->+<HTML+><HEAD+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"+><TITLE+>Chasing Bottoms (Index)</TITLE+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"+></HEAD+><BODY+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="topbar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "+></TD+><TD CLASS="title"+>Chasing Bottoms</TD+><TD CLASS="topbut"+><A HREF="index.html"+>Contents</A+></TD+><TD CLASS="topbut"+><A HREF="doc-index.html"+>Index</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD+><A HREF="doc-index-A.html"+>A</A+></TD+><TD+><A HREF="doc-index-B.html"+>B</A+></TD+><TD+><A HREF="doc-index-C.html"+>C</A+></TD+><TD+><A HREF="doc-index-E.html"+>E</A+></TD+><TD+><A HREF="doc-index-F.html"+>F</A+></TD+><TD+><A HREF="doc-index-G.html"+>G</A+></TD+><TD+><A HREF="doc-index-I.html"+>I</A+></TD+><TD+><A HREF="doc-index-L.html"+>L</A+></TD+><TD+><A HREF="doc-index-M.html"+>M</A+></TD+><TD+><A HREF="doc-index-N.html"+>N</A+></TD+><TD+><A HREF="doc-index-O.html"+>O</A+></TD+><TD+><A HREF="doc-index-P.html"+>P</A+></TD+><TD+><A HREF="doc-index-R.html"+>R</A+></TD+><TD+><A HREF="doc-index-S.html"+>S</A+></TD+><TD+><A HREF="doc-index-T.html"+>T</A+></TD+><TD+><A HREF="doc-index-V.html"+>V</A+></TD+><TD+><A HREF="doc-index-47.html"+>/</A+></TD+><TD+><A HREF="doc-index-60.html"+><</A+></TD+><TD+><A HREF="doc-index-61.html"+>=</A+></TD+><TD+><A HREF="doc-index-62.html"+>></A+></TD+><TD+><A HREF="doc-index-92.html"+>\</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="section1"+>Index (N)</TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD CLASS="indexentry"+>Nat</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-Nat.html#t%3ANat"+>Test.ChasingBottoms.Nat</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>NonTermination</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-TimeOut.html#v%3ANonTermination"+>Test.ChasingBottoms.TimeOut</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>natrec</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-Nat.html#v%3Anatrec"+>Test.ChasingBottoms.Nat</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>noTweak</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-SemanticOrd.html#v%3AnoTweak"+>Test.ChasingBottoms.SemanticOrd</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>nonBottomError</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-IsBottom.html#v%3AnonBottomError"+>Test.ChasingBottoms.IsBottom</A+>, Test.ChasingBottoms</TD+></TR+></TABLE+></TD+></TR+></TABLE+></BODY+></HTML+>
+ docs/doc-index-O.html view
@@ -0,0 +1,146 @@+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">+<!--Rendered using the Haskell Html Library v0.2-->+<HTML+><HEAD+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"+><TITLE+>Chasing Bottoms (Index)</TITLE+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"+></HEAD+><BODY+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="topbar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "+></TD+><TD CLASS="title"+>Chasing Bottoms</TD+><TD CLASS="topbut"+><A HREF="index.html"+>Contents</A+></TD+><TD CLASS="topbut"+><A HREF="doc-index.html"+>Index</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD+><A HREF="doc-index-A.html"+>A</A+></TD+><TD+><A HREF="doc-index-B.html"+>B</A+></TD+><TD+><A HREF="doc-index-C.html"+>C</A+></TD+><TD+><A HREF="doc-index-E.html"+>E</A+></TD+><TD+><A HREF="doc-index-F.html"+>F</A+></TD+><TD+><A HREF="doc-index-G.html"+>G</A+></TD+><TD+><A HREF="doc-index-I.html"+>I</A+></TD+><TD+><A HREF="doc-index-L.html"+>L</A+></TD+><TD+><A HREF="doc-index-M.html"+>M</A+></TD+><TD+><A HREF="doc-index-N.html"+>N</A+></TD+><TD+><A HREF="doc-index-O.html"+>O</A+></TD+><TD+><A HREF="doc-index-P.html"+>P</A+></TD+><TD+><A HREF="doc-index-R.html"+>R</A+></TD+><TD+><A HREF="doc-index-S.html"+>S</A+></TD+><TD+><A HREF="doc-index-T.html"+>T</A+></TD+><TD+><A HREF="doc-index-V.html"+>V</A+></TD+><TD+><A HREF="doc-index-47.html"+>/</A+></TD+><TD+><A HREF="doc-index-60.html"+><</A+></TD+><TD+><A HREF="doc-index-61.html"+>=</A+></TD+><TD+><A HREF="doc-index-62.html"+>></A+></TD+><TD+><A HREF="doc-index-92.html"+>\</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="section1"+>Index (O)</TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD CLASS="indexentry"+>oneof'</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#v%3Aoneof%27"+>Test.ChasingBottoms.ContinuousFunctions</A+>, Test.ChasingBottoms</TD+></TR+></TABLE+></TD+></TR+></TABLE+></BODY+></HTML+>
+ docs/doc-index-P.html view
@@ -0,0 +1,166 @@+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">+<!--Rendered using the Haskell Html Library v0.2-->+<HTML+><HEAD+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"+><TITLE+>Chasing Bottoms (Index)</TITLE+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"+></HEAD+><BODY+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="topbar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "+></TD+><TD CLASS="title"+>Chasing Bottoms</TD+><TD CLASS="topbut"+><A HREF="index.html"+>Contents</A+></TD+><TD CLASS="topbut"+><A HREF="doc-index.html"+>Index</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD+><A HREF="doc-index-A.html"+>A</A+></TD+><TD+><A HREF="doc-index-B.html"+>B</A+></TD+><TD+><A HREF="doc-index-C.html"+>C</A+></TD+><TD+><A HREF="doc-index-E.html"+>E</A+></TD+><TD+><A HREF="doc-index-F.html"+>F</A+></TD+><TD+><A HREF="doc-index-G.html"+>G</A+></TD+><TD+><A HREF="doc-index-I.html"+>I</A+></TD+><TD+><A HREF="doc-index-L.html"+>L</A+></TD+><TD+><A HREF="doc-index-M.html"+>M</A+></TD+><TD+><A HREF="doc-index-N.html"+>N</A+></TD+><TD+><A HREF="doc-index-O.html"+>O</A+></TD+><TD+><A HREF="doc-index-P.html"+>P</A+></TD+><TD+><A HREF="doc-index-R.html"+>R</A+></TD+><TD+><A HREF="doc-index-S.html"+>S</A+></TD+><TD+><A HREF="doc-index-T.html"+>T</A+></TD+><TD+><A HREF="doc-index-V.html"+>V</A+></TD+><TD+><A HREF="doc-index-47.html"+>/</A+></TD+><TD+><A HREF="doc-index-60.html"+><</A+></TD+><TD+><A HREF="doc-index-61.html"+>=</A+></TD+><TD+><A HREF="doc-index-62.html"+>></A+></TD+><TD+><A HREF="doc-index-92.html"+>\</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="section1"+>Index (P)</TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD CLASS="indexentry" COLSPAN="2"+>PatternMatch</TD+></TR+><TR+><TD CLASS="indexannot"+>1 (Type/Class)</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#t%3APatternMatch"+>Test.ChasingBottoms.ContinuousFunctions</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexannot"+>2 (Data Constructor)</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#v%3APatternMatch"+>Test.ChasingBottoms.ContinuousFunctions</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>Prec</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-ApproxShow.html#t%3APrec"+>Test.ChasingBottoms.ApproxShow</A+>, Test.ChasingBottoms</TD+></TR+></TABLE+></TD+></TR+></TABLE+></BODY+></HTML+>
+ docs/doc-index-R.html view
@@ -0,0 +1,154 @@+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">+<!--Rendered using the Haskell Html Library v0.2-->+<HTML+><HEAD+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"+><TITLE+>Chasing Bottoms (Index)</TITLE+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"+></HEAD+><BODY+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="topbar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "+></TD+><TD CLASS="title"+>Chasing Bottoms</TD+><TD CLASS="topbut"+><A HREF="index.html"+>Contents</A+></TD+><TD CLASS="topbut"+><A HREF="doc-index.html"+>Index</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD+><A HREF="doc-index-A.html"+>A</A+></TD+><TD+><A HREF="doc-index-B.html"+>B</A+></TD+><TD+><A HREF="doc-index-C.html"+>C</A+></TD+><TD+><A HREF="doc-index-E.html"+>E</A+></TD+><TD+><A HREF="doc-index-F.html"+>F</A+></TD+><TD+><A HREF="doc-index-G.html"+>G</A+></TD+><TD+><A HREF="doc-index-I.html"+>I</A+></TD+><TD+><A HREF="doc-index-L.html"+>L</A+></TD+><TD+><A HREF="doc-index-M.html"+>M</A+></TD+><TD+><A HREF="doc-index-N.html"+>N</A+></TD+><TD+><A HREF="doc-index-O.html"+>O</A+></TD+><TD+><A HREF="doc-index-P.html"+>P</A+></TD+><TD+><A HREF="doc-index-R.html"+>R</A+></TD+><TD+><A HREF="doc-index-S.html"+>S</A+></TD+><TD+><A HREF="doc-index-T.html"+>T</A+></TD+><TD+><A HREF="doc-index-V.html"+>V</A+></TD+><TD+><A HREF="doc-index-47.html"+>/</A+></TD+><TD+><A HREF="doc-index-60.html"+><</A+></TD+><TD+><A HREF="doc-index-61.html"+>=</A+></TD+><TD+><A HREF="doc-index-62.html"+>></A+></TD+><TD+><A HREF="doc-index-92.html"+>\</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="section1"+>Index (R)</TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD CLASS="indexentry"+>Result</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-TimeOut.html#t%3AResult"+>Test.ChasingBottoms.TimeOut</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>resize'</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#v%3Aresize%27"+>Test.ChasingBottoms.ContinuousFunctions</A+>, Test.ChasingBottoms</TD+></TR+></TABLE+></TD+></TR+></TABLE+></BODY+></HTML+>
+ docs/doc-index-S.html view
@@ -0,0 +1,194 @@+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">+<!--Rendered using the Haskell Html Library v0.2-->+<HTML+><HEAD+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"+><TITLE+>Chasing Bottoms (Index)</TITLE+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"+></HEAD+><BODY+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="topbar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "+></TD+><TD CLASS="title"+>Chasing Bottoms</TD+><TD CLASS="topbut"+><A HREF="index.html"+>Contents</A+></TD+><TD CLASS="topbut"+><A HREF="doc-index.html"+>Index</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD+><A HREF="doc-index-A.html"+>A</A+></TD+><TD+><A HREF="doc-index-B.html"+>B</A+></TD+><TD+><A HREF="doc-index-C.html"+>C</A+></TD+><TD+><A HREF="doc-index-E.html"+>E</A+></TD+><TD+><A HREF="doc-index-F.html"+>F</A+></TD+><TD+><A HREF="doc-index-G.html"+>G</A+></TD+><TD+><A HREF="doc-index-I.html"+>I</A+></TD+><TD+><A HREF="doc-index-L.html"+>L</A+></TD+><TD+><A HREF="doc-index-M.html"+>M</A+></TD+><TD+><A HREF="doc-index-N.html"+>N</A+></TD+><TD+><A HREF="doc-index-O.html"+>O</A+></TD+><TD+><A HREF="doc-index-P.html"+>P</A+></TD+><TD+><A HREF="doc-index-R.html"+>R</A+></TD+><TD+><A HREF="doc-index-S.html"+>S</A+></TD+><TD+><A HREF="doc-index-T.html"+>T</A+></TD+><TD+><A HREF="doc-index-V.html"+>V</A+></TD+><TD+><A HREF="doc-index-47.html"+>/</A+></TD+><TD+><A HREF="doc-index-60.html"+><</A+></TD+><TD+><A HREF="doc-index-61.html"+>=</A+></TD+><TD+><A HREF="doc-index-62.html"+>></A+></TD+><TD+><A HREF="doc-index-92.html"+>\</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="section1"+>Index (S)</TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD CLASS="indexentry"+>SemanticEq</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-SemanticOrd.html#t%3ASemanticEq"+>Test.ChasingBottoms.SemanticOrd</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>SemanticOrd</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-SemanticOrd.html#t%3ASemanticOrd"+>Test.ChasingBottoms.SemanticOrd</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>semanticCompare</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-SemanticOrd.html#v%3AsemanticCompare"+>Test.ChasingBottoms.SemanticOrd</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>semanticEq</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-SemanticOrd.html#v%3AsemanticEq"+>Test.ChasingBottoms.SemanticOrd</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>semanticJoin</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-SemanticOrd.html#v%3AsemanticJoin"+>Test.ChasingBottoms.SemanticOrd</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>semanticMeet</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-SemanticOrd.html#v%3AsemanticMeet"+>Test.ChasingBottoms.SemanticOrd</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>sized'</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#v%3Asized%27"+>Test.ChasingBottoms.ContinuousFunctions</A+>, Test.ChasingBottoms</TD+></TR+></TABLE+></TD+></TR+></TABLE+></BODY+></HTML+>
+ docs/doc-index-T.html view
@@ -0,0 +1,206 @@+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">+<!--Rendered using the Haskell Html Library v0.2-->+<HTML+><HEAD+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"+><TITLE+>Chasing Bottoms (Index)</TITLE+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"+></HEAD+><BODY+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="topbar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "+></TD+><TD CLASS="title"+>Chasing Bottoms</TD+><TD CLASS="topbut"+><A HREF="index.html"+>Contents</A+></TD+><TD CLASS="topbut"+><A HREF="doc-index.html"+>Index</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD+><A HREF="doc-index-A.html"+>A</A+></TD+><TD+><A HREF="doc-index-B.html"+>B</A+></TD+><TD+><A HREF="doc-index-C.html"+>C</A+></TD+><TD+><A HREF="doc-index-E.html"+>E</A+></TD+><TD+><A HREF="doc-index-F.html"+>F</A+></TD+><TD+><A HREF="doc-index-G.html"+>G</A+></TD+><TD+><A HREF="doc-index-I.html"+>I</A+></TD+><TD+><A HREF="doc-index-L.html"+>L</A+></TD+><TD+><A HREF="doc-index-M.html"+>M</A+></TD+><TD+><A HREF="doc-index-N.html"+>N</A+></TD+><TD+><A HREF="doc-index-O.html"+>O</A+></TD+><TD+><A HREF="doc-index-P.html"+>P</A+></TD+><TD+><A HREF="doc-index-R.html"+>R</A+></TD+><TD+><A HREF="doc-index-S.html"+>S</A+></TD+><TD+><A HREF="doc-index-T.html"+>T</A+></TD+><TD+><A HREF="doc-index-V.html"+>V</A+></TD+><TD+><A HREF="doc-index-47.html"+>/</A+></TD+><TD+><A HREF="doc-index-60.html"+><</A+></TD+><TD+><A HREF="doc-index-61.html"+>=</A+></TD+><TD+><A HREF="doc-index-62.html"+>></A+></TD+><TD+><A HREF="doc-index-92.html"+>\</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="section1"+>Index (T)</TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD CLASS="indexentry" COLSPAN="2"+>Tweak</TD+></TR+><TR+><TD CLASS="indexannot"+>1 (Type/Class)</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-SemanticOrd.html#t%3ATweak"+>Test.ChasingBottoms.SemanticOrd</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexannot"+>2 (Data Constructor)</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-SemanticOrd.html#v%3ATweak"+>Test.ChasingBottoms.SemanticOrd</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>timeOut</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-TimeOut.html#v%3AtimeOut"+>Test.ChasingBottoms.TimeOut</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>timeOut'</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-TimeOut.html#v%3AtimeOut%27"+>Test.ChasingBottoms.TimeOut</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>timeOutLimit</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-SemanticOrd.html#v%3AtimeOutLimit"+>Test.ChasingBottoms.SemanticOrd</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>timeOutMicro</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-TimeOut.html#v%3AtimeOutMicro"+>Test.ChasingBottoms.TimeOut</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>timeOutMicro'</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-TimeOut.html#v%3AtimeOutMicro%27"+>Test.ChasingBottoms.TimeOut</A+>, Test.ChasingBottoms</TD+></TR+><TR+><TD CLASS="indexentry"+>transform</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html#v%3Atransform"+>Test.ChasingBottoms.ContinuousFunctions</A+>, Test.ChasingBottoms</TD+></TR+></TABLE+></TD+></TR+></TABLE+></BODY+></HTML+>
+ docs/doc-index-V.html view
@@ -0,0 +1,146 @@+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">+<!--Rendered using the Haskell Html Library v0.2-->+<HTML+><HEAD+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"+><TITLE+>Chasing Bottoms (Index)</TITLE+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"+></HEAD+><BODY+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="topbar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "+></TD+><TD CLASS="title"+>Chasing Bottoms</TD+><TD CLASS="topbut"+><A HREF="index.html"+>Contents</A+></TD+><TD CLASS="topbut"+><A HREF="doc-index.html"+>Index</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD+><A HREF="doc-index-A.html"+>A</A+></TD+><TD+><A HREF="doc-index-B.html"+>B</A+></TD+><TD+><A HREF="doc-index-C.html"+>C</A+></TD+><TD+><A HREF="doc-index-E.html"+>E</A+></TD+><TD+><A HREF="doc-index-F.html"+>F</A+></TD+><TD+><A HREF="doc-index-G.html"+>G</A+></TD+><TD+><A HREF="doc-index-I.html"+>I</A+></TD+><TD+><A HREF="doc-index-L.html"+>L</A+></TD+><TD+><A HREF="doc-index-M.html"+>M</A+></TD+><TD+><A HREF="doc-index-N.html"+>N</A+></TD+><TD+><A HREF="doc-index-O.html"+>O</A+></TD+><TD+><A HREF="doc-index-P.html"+>P</A+></TD+><TD+><A HREF="doc-index-R.html"+>R</A+></TD+><TD+><A HREF="doc-index-S.html"+>S</A+></TD+><TD+><A HREF="doc-index-T.html"+>T</A+></TD+><TD+><A HREF="doc-index-V.html"+>V</A+></TD+><TD+><A HREF="doc-index-47.html"+>/</A+></TD+><TD+><A HREF="doc-index-60.html"+><</A+></TD+><TD+><A HREF="doc-index-61.html"+>=</A+></TD+><TD+><A HREF="doc-index-62.html"+>></A+></TD+><TD+><A HREF="doc-index-92.html"+>\</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="section1"+>Index (V)</TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD CLASS="indexentry"+>Value</TD+><TD CLASS="indexlinks"+><A HREF="Test-ChasingBottoms-TimeOut.html#v%3AValue"+>Test.ChasingBottoms.TimeOut</A+>, Test.ChasingBottoms</TD+></TR+></TABLE+></TD+></TR+></TABLE+></BODY+></HTML+>
+ docs/doc-index.html view
@@ -0,0 +1,132 @@+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">+<!--Rendered using the Haskell Html Library v0.2-->+<HTML+><HEAD+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"+><TITLE+>Chasing Bottoms (Index)</TITLE+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"+></HEAD+><BODY+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="topbar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "+></TD+><TD CLASS="title"+>Chasing Bottoms</TD+><TD CLASS="topbut"+><A HREF="index.html"+>Contents</A+></TD+><TD CLASS="topbut"+><A HREF="doc-index.html"+>Index</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="section1"+>Index</TD+></TR+><TR+><TD+><TABLE CELLPADDING="0" CELLSPACING="5"+><TR+><TD+><A HREF="doc-index-A.html"+>A</A+></TD+><TD+><A HREF="doc-index-B.html"+>B</A+></TD+><TD+><A HREF="doc-index-C.html"+>C</A+></TD+><TD+><A HREF="doc-index-E.html"+>E</A+></TD+><TD+><A HREF="doc-index-F.html"+>F</A+></TD+><TD+><A HREF="doc-index-G.html"+>G</A+></TD+><TD+><A HREF="doc-index-I.html"+>I</A+></TD+><TD+><A HREF="doc-index-L.html"+>L</A+></TD+><TD+><A HREF="doc-index-M.html"+>M</A+></TD+><TD+><A HREF="doc-index-N.html"+>N</A+></TD+><TD+><A HREF="doc-index-O.html"+>O</A+></TD+><TD+><A HREF="doc-index-P.html"+>P</A+></TD+><TD+><A HREF="doc-index-R.html"+>R</A+></TD+><TD+><A HREF="doc-index-S.html"+>S</A+></TD+><TD+><A HREF="doc-index-T.html"+>T</A+></TD+><TD+><A HREF="doc-index-V.html"+>V</A+></TD+><TD+><A HREF="doc-index-47.html"+>/</A+></TD+><TD+><A HREF="doc-index-60.html"+><</A+></TD+><TD+><A HREF="doc-index-61.html"+>=</A+></TD+><TD+><A HREF="doc-index-62.html"+>></A+></TD+><TD+><A HREF="doc-index-92.html"+>\</A+></TD+></TR+></TABLE+></TD+></TR+></TABLE+></BODY+></HTML+>
+ docs/haddock.css view
@@ -0,0 +1,235 @@+/* -------- Global things --------- */++BODY { + background-color: #ffffff;+ color: #000000;+ font-family: sans-serif;+ } ++A:link { color: #0000e0; text-decoration: none }+A:visited { color: #0000a0; text-decoration: none }+A:hover { background-color: #e0e0ff; text-decoration: none }++TABLE.vanilla {+ width: 100%;+ border-width: 0px;+ /* I can't seem to specify cellspacing or cellpadding properly using CSS... */+}++TABLE.vanilla2 {+ border-width: 0px;+}++/* <TT> font is a little too small in MSIE */+TT { font-size: 100%; }+PRE { font-size: 100%; }++LI P { margin: 0pt } ++TD {+ border-width: 0px;+}++TABLE.narrow {+ border-width: 0px;+}++TD.s8 { height: 8px; }+TD.s15 { height: 15px; }++SPAN.keyword { text-decoration: underline; }++/* Resize the buttom image to match the text size */+IMG.coll { width : 0.75em; height: 0.75em; margin-bottom: 0; margin-right: 0.5em }++/* --------- Contents page ---------- */++DIV.node {+ padding-left: 3em;+}++DIV.cnode {+ padding-left: 1.75em;+}++SPAN.pkg {+ position: absolute;+ left: 50em;+}++/* --------- Documentation elements ---------- */++TD.children {+ padding-left: 25px;+ }++TD.synopsis {+ padding: 2px;+ background-color: #f0f0f0;+ font-family: monospace+ }++TD.decl { + padding: 2px;+ background-color: #f0f0f0; + font-family: monospace;+ vertical-align: top;+ }++/* + arg is just like decl, except that wrapping is not allowed. It is+ used for function and constructor arguments which have a text box+ to the right, where if wrapping is allowed the text box squashes up+ the declaration by wrapping it.+*/+TD.arg { + padding: 2px;+ background-color: #f0f0f0; + font-family: monospace;+ vertical-align: top;+ white-space: nowrap;+ }++TD.recfield { padding-left: 20px }++TD.doc { + padding-top: 2px;+ padding-left: 10px;+ }++TD.ndoc { + padding: 2px;+ }++TD.rdoc { + padding: 2px;+ padding-left: 10px;+ width: 100%;+ }++TD.body { + padding-left: 10px+ }++TD.pkg {+ width: 100%;+ padding-left: 10px+}++TD.indexentry {+ vertical-align: top;+ padding-right: 10px+ }++TD.indexannot {+ vertical-align: top;+ padding-left: 20px;+ white-space: nowrap+ }++TD.indexlinks {+ width: 100%+ }++/* ------- Section Headings ------- */++TD.section1 {+ padding-top: 15px;+ font-weight: bold;+ font-size: 150%+ }++TD.section2 {+ padding-top: 10px;+ font-weight: bold;+ font-size: 130%+ }++TD.section3 {+ padding-top: 5px;+ font-weight: bold;+ font-size: 110%+ }++TD.section4 {+ font-weight: bold;+ font-size: 100%+ }++/* -------------- The title bar at the top of the page */++TD.infohead {+ color: #ffffff;+ font-weight: bold;+ padding-right: 10px;+ text-align: left;+}++TD.infoval {+ color: #ffffff;+ padding-right: 10px;+ text-align: left;+}++TD.topbar {+ background-color: #000099;+ padding: 5px;+}++TD.title {+ color: #ffffff;+ padding-left: 10px;+ width: 100%+ }++TD.topbut {+ padding-left: 5px;+ padding-right: 5px;+ border-left-width: 1px;+ border-left-color: #ffffff;+ border-left-style: solid;+ white-space: nowrap;+ }++TD.topbut A:link {+ color: #ffffff+ }++TD.topbut A:visited {+ color: #ffff00+ }++TD.topbut A:hover {+ background-color: #6060ff;+ }++TD.topbut:hover {+ background-color: #6060ff+ }++TD.modulebar { + background-color: #0077dd;+ padding: 5px;+ border-top-width: 1px;+ border-top-color: #ffffff;+ border-top-style: solid;+ }++/* --------- The page footer --------- */++TD.botbar {+ background-color: #000099;+ color: #ffffff;+ padding: 5px+ }+TD.botbar A:link {+ color: #ffffff;+ text-decoration: underline+ }+TD.botbar A:visited {+ color: #ffff00+ }+TD.botbar A:hover {+ background-color: #6060ff+ }+
+ docs/haddock.js view
@@ -0,0 +1,15 @@+// Haddock JavaScript utilities+function toggle(button,id)+{+ var n = document.getElementById(id).style;+ if (n.display == "none")+ {+ button.src = "minus.gif";+ n.display = "block";+ }+ else+ {+ button.src = "plus.gif";+ n.display = "none";+ }+}
+ docs/haskell_icon.gif view
binary file changed (absent → 911 bytes)
+ docs/index.html view
@@ -0,0 +1,488 @@+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">+<!--Rendered using the Haskell Html Library v0.2-->+<HTML+><HEAD+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"+><TITLE+>Chasing Bottoms</TITLE+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"+><SCRIPT SRC="haddock.js" TYPE="text/javascript"+></SCRIPT+></HEAD+><BODY+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="topbar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "+></TD+><TD CLASS="title"+>Chasing Bottoms</TD+><TD CLASS="topbut"+><A HREF="index.html"+>Contents</A+></TD+><TD CLASS="topbut"+><A HREF="doc-index.html"+>Index</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="section1"+>Chasing Bottoms</TD+></TR+><TR+><TD CLASS="doc"+><P+>Do you ever feel the need to test code involving bottoms (e.g. calls to+the <TT+>error</TT+> function), or code involving infinite values? Then this+library could be useful for you.+</P+><P+>It is usually easy to get a grip on bottoms by showing a value and+waiting to see how much gets printed before the first exception is+encountered. However, that quickly gets tiresome and is hard to automate+using e.g. QuickCheck+(<A HREF="http://www.cs.chalmers.se/~rjmh/QuickCheck/"+>http://www.cs.chalmers.se/~rjmh/QuickCheck/</A+>). With this library you+can do the tests as simply as the following examples show.+</P+><P+>Testing explicitly for bottoms:+</P+><DL+><DT+><TT+>> isBottom (head [])</TT+></DT+><DD+> <TT+>True</TT+>+</DD+><DT+><TT+>> isBottom bottom</TT+></DT+><DD+> <TT+>True</TT+>+</DD+><DT+><TT+>> isBottom (\_ -> bottom)</TT+></DT+><DD+> <TT+>False</TT+>+</DD+><DT+><TT+>> isBottom (bottom, bottom)</TT+></DT+><DD+> <TT+>False</TT+>+</DD+></DL+><P+>Comparing finite, partial values:+</P+><DL+><DT+><TT+>> ((bottom, 3) :: (Bool, Int)) ==! (bottom, 2+5-4)</TT+></DT+><DD+> <TT+>True</TT+>+</DD+><DT+><TT+>> ((bottom, bottom) :: (Bool, Int)) <! (bottom, 8)</TT+></DT+><DD+> <TT+>True</TT+>+</DD+></DL+><P+>Showing partial and infinite values (<TT+>\/!</TT+> is join and <TT+>/\!</TT+> is meet):+</P+><DL+><DT+><TT+>> approxShow 4 $ (True, bottom) \/! (bottom, 'b')</TT+></DT+><DD+> <TT+>"Just (True, 'b')"</TT+>+</DD+><DT+><TT+>> approxShow 4 $ (True, bottom) /\! (bottom, 'b')</TT+></DT+><DD+> <TT+>"(_|_, _|_)"</TT+>+</DD+><DT+><TT+>> approxShow 4 $ ([1..] :: [Int])</TT+></DT+><DD+> <TT+>"[1, 2, 3, _"</TT+>+</DD+><DT+><TT+>> approxShow 4 $ (cycle [bottom] :: [Bool])</TT+></DT+><DD+> <TT+>"[_|_, _|_, _|_, _"</TT+>+</DD+></DL+><P+>Approximately comparing infinite, partial values:+</P+><DL+><DT+><TT+>> approx 100 [2,4..] ==! approx 100 (filter even [1..] :: [Int])</TT+></DT+><DD+> <TT+>True</TT+>+</DD+><DT+><TT+>> approx 100 [2,4..] /=! approx 100 (filter even [bottom..] :: [Int])</TT+></DT+><DD+> <TT+>True</TT+>+</DD+></DL+><P+>The code above relies on the fact that <TT+>bottom</TT+>, just as <TT+>error+"..."</TT+>, <TT+>undefined</TT+> and pattern match failures, yield+exceptions. Sometimes we are dealing with properly non-terminating+computations, such as the following example, and then it can be nice to+be able to apply a time-out:+</P+><DL+><DT+><TT+>> timeOut' 1 (reverse [1..5]) >>= print</TT+></DT+><DD+> <TT+>Value [5,4,3,2,1]</TT+>+</DD+><DT+><TT+>> timeOut' 1 (reverse [1..]) >>= print</TT+></DT+><DD+> <TT+>NonTermination</TT+>+</DD+></DL+><P+>The time-out functionality can be used to treat "slow" computations as+bottoms:+</P+><DL+><DT+><TT+>> let tweak = Tweak { approxDepth = Just 5, timeOutLimit = Just 2 }</TT+></DT+><DD+>+</DD+><DT+><TT+>> semanticEq tweak (reverse [1..], [1..]) (bottom :: [Int], [1..] :: [Int])</TT+></DT+><DD+> <TT+>True</TT+>+</DD+><DT+><TT+>> let tweak = noTweak { timeOutLimit = Just 2 }</TT+></DT+><DD+>+</DD+><DT+><TT+>> semanticJoin tweak (reverse [1..], True) ([] :: [Int], bottom)</TT+></DT+><DD+> <TT+>Just ([],True)</TT+>+</DD+></DL+><P+>This can of course be dangerous:+</P+><DL+><DT+><TT+>> let tweak = noTweak { timeOutLimit = Just 0 }</TT+></DT+><DD+>+</DD+><DT+><TT+>> semanticEq tweak (reverse [1..100000000]) (bottom :: [Integer])</TT+></DT+><DD+> <TT+>True</TT+>+</DD+></DL+><P+>Timeouts can also be applied to <TT+>IO</TT+> computations:+</P+><DL+><DT+><TT+>> let primes = unfoldr (\(x:xs) -> Just (x, filter ((/= 0) . (`mod` x)) xs)) [2..]</TT+></DT+><DD+>+</DD+><DT+><TT+>> timeOutMicro 100 (print $ filter ((== 1) . (`mod` 83)) primes) >>= print</TT+></DT+><DD+> <TT+>[167,499NonTermination</TT+>+</DD+><DT+><TT+>> timeOutMicro 100 (print $ take 4 $ filter ((== 1) . (`mod` 83)) primes) >>= print</TT+></DT+><DD+> <TT+>[167,499,997NonTermination</TT+>+</DD+><DT+><TT+>> timeOutMicro 100 (print $ take 4 $ filter ((== 1) . (`mod` 83)) primes) >>= print</TT+></DT+><DD+> <TT+>[167,499,997,1163]</TT+>+</DD+><DT+><TT+> </TT+></DT+><DD+> <TT+>Value ()</TT+>+</DD+></DL+><P+>All the type annotations above are required.+</P+><P+>For the underlying theory and a larger example involving use of+QuickCheck, see the article "Chasing Bottoms, A Case Study in Program+Verification in the Presence of Partial and Infinite Values"+(<A HREF="http://www.cs.chalmers.se/~nad/publications/danielsson-jansson-mpc2004.html"+>http://www.cs.chalmers.se/~nad/publications/danielsson-jansson-mpc2004.html</A+>).+</P+><P+>The code has been tested under GHC 6.8. Most parts can probably be+ported to other Haskell compilers, but that would require some work.+The <TT+>TimeOut</TT+> functions require preemptive scheduling, and most of the+rest requires <TT+>Data.Generics</TT+>; <TT+>isBottom</TT+> only requires exceptions,+though.+</P+><P+>Source code: <A HREF="http://www.cs.chalmers.se/~nad/software/ChasingBottoms/ChasingBottoms.tar.gz"+>http://www.cs.chalmers.se/~nad/software/ChasingBottoms/ChasingBottoms.tar.gz</A+>.+</P+></TD+></TR+><TR+><TD CLASS="section1"+>Modules</TD+></TR+><TR+><TD+><TABLE CLASS="vanilla2" CELLSPACING="0" CELLPADDING="0"+><TR+><TD STYLE="width: 50em"+><IMG SRC="minus.gif" CLASS="coll" ONCLICK="toggle(this,'n:0')" ALT="show/hide"+>Test</TD+><TD+></TD+><TD+></TD+></TR+><TR+><TD STYLE="padding: 0; padding-left: 2em" COLSPAN="3"+><TABLE CLASS="vanilla2" CELLSPACING="0" CELLPADDING="0" ID="n:0" STYLE="display:block;"+><TR+><TD STYLE="width: 48em"+><IMG SRC="minus.gif" CLASS="coll" ONCLICK="toggle(this,'n:1')" ALT="show/hide"+><A HREF="Test-ChasingBottoms.html"+>Test.ChasingBottoms</A+></TD+><TD+></TD+><TD+></TD+></TR+><TR+><TD STYLE="padding: 0; padding-left: 2em" COLSPAN="3"+><TABLE CLASS="vanilla2" CELLSPACING="0" CELLPADDING="0" ID="n:1" STYLE="display:block;"+><TR+><TD STYLE="padding-left: 1.25em;width: 46em"+><A HREF="Test-ChasingBottoms-Approx.html"+>Test.ChasingBottoms.Approx</A+></TD+><TD+></TD+><TD+></TD+></TR+><TR+><TD STYLE="padding-left: 1.25em;width: 46em"+><A HREF="Test-ChasingBottoms-ApproxShow.html"+>Test.ChasingBottoms.ApproxShow</A+></TD+><TD+></TD+><TD+></TD+></TR+><TR+><TD STYLE="padding-left: 1.25em;width: 46em"+><A HREF="Test-ChasingBottoms-ContinuousFunctions.html"+>Test.ChasingBottoms.ContinuousFunctions</A+></TD+><TD+></TD+><TD+></TD+></TR+><TR+><TD STYLE="padding-left: 1.25em;width: 46em"+><A HREF="Test-ChasingBottoms-IsBottom.html"+>Test.ChasingBottoms.IsBottom</A+></TD+><TD+></TD+><TD+></TD+></TR+><TR+><TD STYLE="padding-left: 1.25em;width: 46em"+><A HREF="Test-ChasingBottoms-Nat.html"+>Test.ChasingBottoms.Nat</A+></TD+><TD+></TD+><TD+></TD+></TR+><TR+><TD STYLE="padding-left: 1.25em;width: 46em"+><A HREF="Test-ChasingBottoms-SemanticOrd.html"+>Test.ChasingBottoms.SemanticOrd</A+></TD+><TD+></TD+><TD+></TD+></TR+><TR+><TD STYLE="padding-left: 1.25em;width: 46em"+><A HREF="Test-ChasingBottoms-TimeOut.html"+>Test.ChasingBottoms.TimeOut</A+></TD+><TD+></TD+><TD+></TD+></TR+></TABLE+></TD+></TR+></TABLE+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="botbar"+>Produced by <A HREF="http://www.haskell.org/haddock/"+>Haddock</A+> version 0.7</TD+></TR+></TABLE+></BODY+></HTML+>
+ docs/minus.gif view
binary file changed (absent → 56 bytes)
+ docs/plus.gif view
binary file changed (absent → 59 bytes)