packages feed

acme-omitted 1.1.0.0 → 1.2.0.0

raw patch · 4 files changed

+130/−62 lines, 4 files

Files

+ ChangeLog view
@@ -0,0 +1,5 @@+acme-omitted 1.2.0.0, 2013-10-13+	* Add an alternate implementation of `undefined`+	* Add `isPreludeUndefined` (replaces the old `isUndefined`)+acme-omitted 1.1.0.0, 2013-10-05+	* Initial release
README.markdown view
@@ -6,6 +6,7 @@ acme-omitted provides  - a universal definition of "omitted"; and-- functions to observe the difference between omitted and undefined.+- an alternative to `Prelude.undefined`; and+- functions to observe the difference  The library is standards-compliant, type-safe, and user-friendly.
acme-omitted.cabal view
@@ -1,16 +1,16 @@ Name:                acme-omitted-Version:             1.1.0.0+Version:             1.2.0.0 Synopsis:            Purely functional omitted content for Haskell Category:            Acme Stability:           stable Description:-    Standard Haskell lacks the ability to express the notion of \"omitted content\",-    making it impossible to distinguish the truly \"undefined\" and the-    merely \"omitted\".+    Standard Haskell lacks the ability to express the notion of+    \"omitted content\", making it impossible to distinguish the truly+    \"undefined\" and the merely \"omitted\".     .-    acme-omitted implements a universal definition of \"omitted\" and provides-    means of observing whether a definition has been omitted or if it is truly-    undefined.+    acme-omitted provides a universal definition of \"omitted\",+    an alternative to 'Prelude.undefined', and functions to observe+    the difference.     .     The library is standards-compliant, type-safe, and user-friendly. @@ -24,6 +24,7 @@  Extra-source-files:     README.markdown+  , ChangeLog  Build-type:          Simple Cabal-version:       >= 1.10
src/Acme/Omitted.hs view
@@ -1,4 +1,4 @@-{- |+{-| Module      : Acme.Omitted Description : A universal definition of omitted content Copyright   : (c) 2013 Joachim Fasting@@ -8,44 +8,83 @@ Stability   : stable Portability : portable -A universal definition of \"omitted content\" and methods-for observing whether a definition is merely \"omitted\" or-truly \"undefined\".+A universal definition of \"omitted content\", an alternative to+'Prelude.undefined', and methods for observing whether a definition is+merely \"omitted\" or truly \"undefined\". -}  module Acme.Omitted   (+    -- * Usage+    --+    -- $usage+     -- * A universal definition of \"omitted content\"     --     -- $omitted     omitted   , (...) +    -- * \"undefined\" redefined+    --+    -- $undefined+  , undefined+     -- * Observing the difference between \"omitted\" and \"undefined\"     --     -- $observing   , isOmitted   , isUndefined+  , isPreludeUndefined   ) where +import Prelude hiding (undefined) import qualified Control.Exception as E ---------------------------------------------------------------------------- $omitted------ The difference between \"omitted\" and \"undefined\" is that the--- programmer may choose to omit something but he cannot define the--- undefinable.--- The former is contingent on the whims of the programmer, the latter--- a fundamental truth.------ Operationally, there is no difference between undefined and omitted;--- attempting to evaluate either is treated as an error.------ Ideally, programmers would only ever use 'undefined' for things that--- are truly undefined, e.g., division by zero, and use 'omitted' for--- definitions that have yet to be written or that are currently not needed.+{-$usage +This module provides an alternative implementation of+\"Prelude.undefined\".+To avoid name clashes with the "Prelude", use a qualified+import or otherwise resolve the conflict.++Use thus++@+module AwesomeSauce where++import Prelude hiding (undefined)+import Acme.Omitted++tooLazyToDefine     = (...)++actuallyUndefinable = undefined++main = do+  merelyOmitted <- 'isOmitted' tooLazyToDefine+  putStrLn \"Definition was merely omitted\"+  (...)+  trulyUndefined <- 'isUndefined' actuallyUndefinable+  putStrLn \"Definition is truly undefinable\"+@+-}++{-$omitted++The difference between \"omitted\" and \"undefined\" is that the+programmer may choose to omit something but she cannot define the+undefinable.+The former is contingent on the whims of the programmer, the latter+a fundamental truth.++Operationally, there is no difference between undefined and omitted;+attempting to evaluate either is treated as an error.++Ideally, programmers would only ever use 'undefined' for things that+are truly undefined, e.g., division by zero, and use 'omitted' for+definitions that have yet to be written or that are currently not needed.+-}+ -- | Alternative syntax for 'omitted' that has been carefully -- optimised for programmer convenience and visual presentation -- (e.g., for use in printed documents).@@ -62,42 +101,60 @@ omitted :: a omitted = error "omitted" ---------------------------------------------------------------------------- $observing------ The following definitions allow the user to discriminate undefined--- omitted values.--- Some caveats apply, however.------ Though 'isUndefined' arguably could be a pure function (what is by--- definition undefinable shall always remain undefined), we feel it most--- appropriate to keep both 'isOmitted' and 'isUndefined' in 'IO', for--- reasons of symmetry and because the distinction between omitted and--- undefined is a 'GHC.Prim.RealWorld' concern (in the end, both denote the--- same value, i.e., bottom).------ Another reason to keep 'isUndefined' in 'IO' is the regrettable state of--- modern Haskell, which has forced programmers to use 'undefined' for all--- sorts of purposes where 'omitted' should have been used instead.--- Thus it is unsound to assume that 'undefined' values will remain so, or--- indeed make any assumptions about it at all.+{-$undefined++Lacking a dedicated name for omitted defintions, users of Standard+Haskell have been left with no choice but to use \"undefined\" for both+the undefinable and the omitted.+This makes the standard implementation of \"undefined\" deficient, we+cannot be sure what the programmer has intended, only that the definition is+missing.+Here is an alternate implementation, similar in most every way to the+standard implementation, but free from conceptual contamination.+-}++-- | Denotes all values that are, fundamentally, undefinable. ----- The confounding of \"undefined\" and \"omitted\" also means that,--- as it stands, 'isUndefined' will return bogus results for some uses of--- 'undefined'.--- A possible refinement is to provide an alternative to \"Prelude.undefined\"--- that could be assumed to only represent values that are \"truly undefined\".--- For now, 'isUndefined' is provided as a convenience, but users are adviced to--- not rely on its results.--- Users are, however, encouraged to file bugs against libraries making unsound--- use of 'undefined'.+-- The implicit (as in not statically enforcable) contract of 'undefined'+-- is that it will never be used for merely omitted definitions.+-- For that, see 'omitted'.+undefined :: a+undefined = error "Acme.Omitted.undefined" +{-$observing++Recent developments in the theory of representing undefined things have+made it possible for programmers to more clearly state their intentions,+by using our 'undefined' rather than the one from the Haskell 2010 "Prelude".+There is, however, still no way to statically ensure that 'undefined' is used+correctly.+Consequently, 'isUndefined' will return bogus results every now and then (which is why+it is modelled as an 'IO' action and not a pure function).++Nevertheless, the user can identify incorrect uses of 'undefined' more easily+than before.+To wit, if++@+isUndefined twoPlusTwo = return True+@++then, surely, something is amiss.+We know that the programmer has made the mistake of believing @2+2@ to be undefined,+that she has not simply run out of time or gotten an important phone call while+writing down the solution.++For backwards-compatibility, we also support detecting the standard+implementation of undefined, about which we cannot infer anything+except that its evaluation will terminate with no useful result.+-}+ -- | Answer the age-old question \"was this definition omitted?\" -- -- @--- isOmitted 0         = return False--- isOmitted undefined = return False--- isOmitted omitted   = return True+-- isOmitted 0           = return False+-- isOmitted 'undefined' = return False+-- isOmitted 'omitted'   = return True -- @ isOmitted :: a -> IO Bool isOmitted = isErrorCall "omitted"@@ -105,12 +162,16 @@ -- | ... or is it really 'undefined'? -- -- @--- isUndefined 0         = return False--- isUndefined omitted   = return False--- isUndefined undefined = return True+-- isUndefined 0           = return False+-- isUndefined 'undefined' = return True+-- isUndefined 'omitted'   = return False -- @ isUndefined :: a -> IO Bool-isUndefined = isErrorCall "Prelude.undefined"+isUndefined = isErrorCall "Acme.Omitted.undefined"++-- | A version of 'isUndefined' for \"Prelude.undefined\".+isPreludeUndefined :: a -> IO Bool+isPreludeUndefined = isErrorCall "Prelude.undefined"  isErrorCall :: String -> a -> IO Bool isErrorCall s x = (E.evaluate x >> return False)