acme-omitted 1.2.0.0 → 2.0.0.0
raw patch · 6 files changed
+157/−179 lines, 6 filesdep −hspec-discoverdep ~basedep ~hspec
Dependencies removed: hspec-discover
Dependency ranges changed: base, hspec
Files
- COPYING +1/−1
- ChangeLog +2/−0
- README.markdown +4/−8
- acme-omitted.cabal +14/−19
- src/Acme/Omitted.hs +8/−151
- src/Acme/Undefined.hs +128/−0
COPYING view
@@ -1,4 +1,4 @@-Copyright (c) 2012, 2013 Joachim Fasting+Copyright (c) 2012, 2013, 2014 Joachim Fasting All rights reserved.
ChangeLog view
@@ -1,3 +1,5 @@+acme-omitted 2.0.0.0, 2014-10-20+ * Factor out Acme.Undefined acme-omitted 1.2.0.0, 2013-10-13 * Add an alternate implementation of `undefined` * Add `isPreludeUndefined` (replaces the old `isUndefined`)
README.markdown view
@@ -1,12 +1,8 @@-# acme-omitted: purely functional omitted content for Haskell--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: a name for omitted definitions acme-omitted provides -- a universal definition of "omitted"; and+- a way of indicating that a definition has been "omitted"+ (though not inherently undefinable); and - an alternative to `Prelude.undefined`; and-- functions to observe the difference--The library is standards-compliant, type-safe, and user-friendly.+- the means to observe the difference.
acme-omitted.cabal view
@@ -1,25 +1,20 @@ Name: acme-omitted-Version: 1.2.0.0-Synopsis: Purely functional omitted content for Haskell+Version: 2.0.0.0+Synopsis: A name for omitted definitions 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\".- .- 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.+ acme-omitted provides a way of indicating that a definition+ has been \"omitted\" (though not inherently undefinable), an+ alternative to \"Prelude.undefined\", and the means to observe+ the difference. License: BSD3 License-file: COPYING Author: Joachim Fasting-Maintainer: joachim.fasting@gmail.com-Copyright: (c) 2013 Joachim Fasting+Maintainer: joachifm@fastmail.fm+Copyright: (c) 2013-2014 Joachim Fasting Homepage: https://github.com/joachifm/acme-omitted#readme Extra-source-files:@@ -31,15 +26,16 @@ Source-repository head Type: git- location: git@github.com:joachifm/acme-omitted.git+ location: https://github.com/joachifm/acme-omitted.git Library Default-language: Haskell2010 - Exposed-modules: Acme.Omitted+ Exposed-modules: Acme.Omitted,+ Acme.Undefined Build-depends:- base >= 3.0.3 && < 5+ base >=3 && <5 Hs-Source-Dirs: src @@ -53,6 +49,5 @@ Hs-Source-Dirs: src tests Build-depends:- base >= 3.0.3- , hspec- , hspec-discover+ base >=3 && <5+ , hspec >=1.8.1
src/Acme/Omitted.hs view
@@ -1,90 +1,25 @@ {-| Module : Acme.Omitted-Description : A universal definition of omitted content-Copyright : (c) 2013 Joachim Fasting+Description : A name for omitted definitions+Copyright : (c) 2013-2014 Joachim Fasting License : BSD3 -Maintainer : joachim.fasting@gmail.com+Maintainer : joachifm@fastmail.fm Stability : stable Portability : portable -A universal definition of \"omitted content\", an alternative to-'Prelude.undefined', and methods for observing whether a definition is-merely \"omitted\" or truly \"undefined\".+This module provides the means to indicate that a definition+has been omitted (for whatever reason), as opposed to being+inherently undefinable. -} 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--{-$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).@@ -95,84 +30,6 @@ (...) :: a (...) = omitted --- | The universal omitted content operator.------ This is sufficient to express _all_ types of omitted content+-- | Indicate that a definition has been omitted. omitted :: a-omitted = error "omitted"--{-$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 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 :: a -> IO Bool-isOmitted = isErrorCall "omitted"---- | ... or is it really 'undefined'?------ @--- isUndefined 0 = return False--- isUndefined 'undefined' = return True--- isUndefined 'omitted' = return False--- @-isUndefined :: a -> IO Bool-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)- `E.catch` (\(E.ErrorCall e) -> return $ e == s)+omitted = error "Acme.Omitted.omitted"
+ src/Acme/Undefined.hs view
@@ -0,0 +1,128 @@+{-|+Module : Acme.Undefined+Description : Undefined redefined+Copyright : (c) 2013-2014 Joachim Fasting+License : BSD3++Maintainer : joachifm@fastmail.fm+Stability : stable+Portability : portable++This module provides an alternative implementation of+\"Prelude.undefined\", intended exclusively for denoting+truly undefinable values.+-}++module Acme.Undefined (+ -- * Usage+ -- $usage+ + -- * \"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++{-$usage+@+module AwesomeSauce where++import Prelude hiding (undefined)+import Acme.Omitted+import Acme.Undefined++tooLazyToDefine = (...)++actuallyUndefinable = undefined++main = do+ merelyOmitted <- 'isOmitted' tooLazyToDefine+ putStrLn \"Definition was merely omitted\"+ (...)+ trulyUndefined <- 'isUndefined' actuallyUndefinable+ putStrLn \"Definition is truly undefinable\"+@+-}++{-$undefined++Lacking a dedicated name for omitted defintions, users of Standard+Haskell are 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.+The following implementation of undefined is similar in every way to+the standard implementation, but is free from conceptual contamination.+-}++-- | Denotes all values that are, fundamentally, undefinable.+--+-- The contract of 'undefined' is that it will never be used for+-- merely omitted definitions.+undefined :: a+undefined = error "Acme.Undefined.undefined"++{-$observing++Consistent use of 'undefined' and 'omitted' can clarify the intent of the+programmer, but there is still no way to statically prevent incorrect+uses of 'undefined' (e.g., due to ignorance).+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 :: a -> IO Bool+isOmitted = isErrorCall "Acme.Omitted.omitted"++-- | ... or is it really 'undefined'?+--+-- @+-- isUndefined 0 = return False+-- isUndefined 'undefined' = return True+-- isUndefined 'omitted' = return False+-- @+isUndefined :: a -> IO Bool+isUndefined = isErrorCall "Acme.Undefined.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)+ `E.catch` (\(E.ErrorCall e) -> return $ e == s)