summaryrefslogtreecommitdiff
path: root/compiler/utils
diff options
context:
space:
mode:
authorTwan van Laarhoven <twanvl@gmail.com>2013-10-15 20:38:58 +0100
committerKrzysztof Gogolewski <krz.gogolewski@gmail.com>2013-10-15 22:22:48 +0200
commit332eba9d3ff63365818310767a1766370343dcb0 (patch)
treeef7092e38c1620ab73f2fe3160cce5ca1b58b38a /compiler/utils
parente5751265b2593cb9b769feb9c5245324bb82e7db (diff)
downloadhaskell-332eba9d3ff63365818310767a1766370343dcb0.tar.gz
Added comments to BooleanFormula to explain the expression simplifier. (#7633)
Diffstat (limited to 'compiler/utils')
-rw-r--r--compiler/utils/BooleanFormula.hs50
1 files changed, 47 insertions, 3 deletions
diff --git a/compiler/utils/BooleanFormula.hs b/compiler/utils/BooleanFormula.hs
index 3e82e75b1f..8620ef555d 100644
--- a/compiler/utils/BooleanFormula.hs
+++ b/compiler/utils/BooleanFormula.hs
@@ -1,6 +1,9 @@
--------------------------------------------------------------------------------
--- | Boolean formulas without negation (qunatifier free)
-
+-- | Boolean formulas without quantifiers and without negation.
+-- Such a formula consists of variables, conjunctions (and), and disjunctions (or).
+--
+-- This module is used to represent minimal complete definitions for classes.
+--
{-# LANGUAGE DeriveDataTypeable, DeriveFunctor, DeriveFoldable,
DeriveTraversable #-}
@@ -36,13 +39,16 @@ mkFalse, mkTrue :: BooleanFormula a
mkFalse = Or []
mkTrue = And []
+-- Convert a Bool to a BooleanFormula
mkBool :: Bool -> BooleanFormula a
mkBool False = mkFalse
mkBool True = mkTrue
+-- Make a conjunction, and try to simplify
mkAnd :: Eq a => [BooleanFormula a] -> BooleanFormula a
mkAnd = maybe mkFalse (mkAnd' . nub) . concatMapM fromAnd
where
+ -- See Note [Simplification of BooleanFormulas]
fromAnd :: BooleanFormula a -> Maybe [BooleanFormula a]
fromAnd (And xs) = Just xs
-- assume that xs are already simplified
@@ -55,14 +61,50 @@ mkAnd = maybe mkFalse (mkAnd' . nub) . concatMapM fromAnd
mkOr :: Eq a => [BooleanFormula a] -> BooleanFormula a
mkOr = maybe mkTrue (mkOr' . nub) . concatMapM fromOr
where
+ -- See Note [Simplification of BooleanFormulas]
fromOr (Or xs) = Just xs
fromOr (And []) = Nothing
fromOr x = Just [x]
mkOr' [x] = x
mkOr' xs = Or xs
+
+{-
+Note [Simplification of BooleanFormulas]
+~~~~~~~~~~~~~~~~~~~~~~
+The smart constructors (`mkAnd` and `mkOr`) do some attempt to simplify expressions. In particular,
+ 1. Collapsing nested ands and ors, so
+ `(mkAnd [x, And [y,z]]`
+ is represented as
+ `And [x,y,z]`
+ Implemented by `fromAnd`/`fromOr`
+ 2. Collapsing trivial ands and ors, so
+ `mkAnd [x]` becomes just `x`.
+ Implemented by mkAnd' / mkOr'
+ 3. Conjunction with false, disjunction with true is simplified, i.e.
+ `mkAnd [mkFalse,x]` becomes `mkFalse`.
+ 4. Common subexpresion elimination:
+ `mkAnd [x,x,y]` is reduced to just `mkAnd [x,y]`.
+
+This simplification is not exhaustive, in the sense that it will not produce
+the smallest possible equivalent expression. For example,
+`Or [And [x,y], And [x]]` could be simplified to `And [x]`, but it currently
+is not. A general simplifier would need to use something like BDDs.
+
+The reason behind the (crude) simplifier is to make for more user friendly
+error messages. E.g. for the code
+ > class Foo a where
+ > {-# MINIMAL bar, (foo, baq | foo, quux) #-}
+ > instance Foo Int where
+ > bar = ...
+ > baz = ...
+ > quux = ...
+We don't show a ridiculous error message like
+ Implement () and (either (`foo' and ()) or (`foo' and ()))
+-}
+
----------------------------------------------------------------------
--- Evaluation and simplificiation
+-- Evaluation and simplification
----------------------------------------------------------------------
isFalse :: BooleanFormula a -> Bool
@@ -117,6 +159,8 @@ x `implies` Or ys = any (x `implies`) ys
-- Pretty printing
----------------------------------------------------------------------
+-- Pretty print a BooleanFormula,
+-- using the arguments as pretty printers for Var, And and Or respectively
pprBooleanFormula' :: (Rational -> a -> SDoc)
-> (Rational -> [SDoc] -> SDoc)
-> (Rational -> [SDoc] -> SDoc)