safe-failure (empty) → 0.1
raw patch · 4 files changed
+294/−0 lines, 4 filesdep +basedep +control-monad-exceptiondep +control-monad-failuresetup-changed
Dependencies added: base, control-monad-exception, control-monad-failure, extensible-exceptions
Files
- LICENSE +30/−0
- Safe/Failure.hs +219/−0
- Setup.hs +2/−0
- safe-failure.cabal +43/−0
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Neil Mitchell 2007-2008.+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are+met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Neil Mitchell nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Safe/Failure.hs view
@@ -0,0 +1,219 @@+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE FlexibleContexts, FlexibleInstances #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE CPP #-}+{- |+Module : Safe.Fail+Copyright : (c) Neil Mitchell 2007-2008, Jose Iborra 2009+License : BSD3++Maintainer : pepeiborra@gmail.com+Stability : in-progress+Portability : portable++A library for safe functions, based on standard functions that may crash.++This module reexports versions which produce exceptions in an arbitrary 'MonadFailure' monad.++-}++module Safe.Failure (+-- * List Functions+Safe.Failure.head, Safe.Failure.tail,+Safe.Failure.init, Safe.Failure.last,+Safe.Failure.minimum, Safe.Failure.maximum,+Safe.Failure.foldr1, Safe.Failure.foldl1,+Safe.Failure.at, Safe.Failure.lookup,+-- * Maybe functions+Safe.Failure.fromJust,+-- * Other Prelude functions+Safe.Failure.read,+-- * Useful combinators+def, note,+-- * Exceptions+SafeException(..),+HeadFailure(..), TailFailure(..), InitFailure(..), LastFailure(..),+MaximumFailure(..), MinimumFailure(..),+Foldl1Failure(..), Foldr1Failure(..),+IndexFailure(..), LookupFailure(..),+FromJustFailure(..),+ReadFailure(..),+) where++import Control.Exception+import Control.Monad.Failure+import Data.Maybe+import Data.Typeable+#ifdef CME+import Control.Monad.Exception.Throws+#endif++{-| @def@, use it to return a default value in the event of an error.++ E.g. you can define a version of @tail@ which returns a default+ value when the list is empty++> tailDef defaultValue = def defaultValue . tail+-}++def :: a -> Maybe a -> a+def v = fromMaybe v++{-| @note@, use it to fail with an annotated runtime error+-}++note :: Exception e => String -> Either e a -> a+note msg = either (\e -> error (show e ++ ": " ++ msg)) id++data SafeException = forall e. Exception e => SafeException e+ deriving (Typeable)+instance Show SafeException where+ showsPrec p (SafeException e) = ("Safe Exception:" ++) . showsPrec p e+instance Exception SafeException++safeExceptionToException :: Exception e => e -> SomeException+safeExceptionToException = toException . SafeException++safeExceptionFromException :: Exception e => SomeException -> Maybe e+safeExceptionFromException e = do { SafeException e' <- fromException e; cast e'}++liftFailure :: MonadFailure e m => (a -> Bool) -> e -> (a -> b) -> a -> m b+liftFailure test e f val = if test val then failure e else return (f val)+++data TailFailure = TailFailure deriving (Show,Typeable)+instance Exception TailFailure where+ fromException = safeExceptionFromException+ toException = safeExceptionToException++tail :: MonadFailure TailFailure m => [a] -> m [a]+tail = liftFailure null TailFailure Prelude.tail+++data InitFailure = InitFailure deriving (Show,Typeable)+instance Exception InitFailure where+ fromException = safeExceptionFromException+ toException = safeExceptionToException++init :: MonadFailure InitFailure m => [a] -> m [a]+init = liftFailure null InitFailure Prelude.init+++data HeadFailure = HeadFailure deriving (Show,Typeable)+instance Exception HeadFailure where+ fromException = safeExceptionFromException+ toException = safeExceptionToException++head :: MonadFailure HeadFailure m => [a] -> m a+head = liftFailure null HeadFailure Prelude.head+++data LastFailure = LastFailure deriving (Show,Typeable)+instance Exception LastFailure where+ fromException = safeExceptionFromException+ toException = safeExceptionToException++last :: MonadFailure LastFailure m => [a] -> m a+last = liftFailure null LastFailure Prelude.last+++data MinimumFailure = MinimumFailure deriving (Show,Typeable)+instance Exception MinimumFailure where+ fromException = safeExceptionFromException+ toException = safeExceptionToException++minimum :: (Ord a, MonadFailure MinimumFailure m) => [a] -> m a+minimum = liftFailure null MinimumFailure Prelude.minimum+++data MaximumFailure = MaximumFailure deriving (Show,Typeable)+instance Exception MaximumFailure where+ fromException = safeExceptionFromException+ toException = safeExceptionToException++maximum :: (Ord a, MonadFailure MaximumFailure m) => [a] -> m a+maximum = liftFailure null MaximumFailure Prelude.maximum+++data Foldr1Failure = Foldr1Failure deriving (Show,Typeable)+instance Exception Foldr1Failure where+ fromException = safeExceptionFromException+ toException = safeExceptionToException++foldr1 :: MonadFailure Foldr1Failure m => (a -> a -> a) -> [a] -> m a+foldr1 f = liftFailure null Foldr1Failure (Prelude.foldr1 f)+++data Foldl1Failure = Foldl1Failure deriving (Show,Typeable)+instance Exception Foldl1Failure where+ fromException = safeExceptionFromException+ toException = safeExceptionToException++foldl1 :: MonadFailure Foldl1Failure m => (a -> a -> a) -> [a] -> m a+foldl1 f = liftFailure null Foldl1Failure (Prelude.foldl1 f)+++data FromJustFailure = FromJustFailure deriving (Show,Typeable)+instance Exception FromJustFailure where+ fromException = safeExceptionFromException+ toException = safeExceptionToException++fromJust :: MonadFailure FromJustFailure m => Maybe a -> m a+fromJust = liftFailure isNothing FromJustFailure Data.Maybe.fromJust+++data IndexFailure = IndexFailure Int deriving (Show,Typeable)+instance Exception IndexFailure where+ fromException = safeExceptionFromException+ toException = safeExceptionToException++at :: MonadFailure IndexFailure m => [a] -> Int -> m a+at xs n+ | n < 0 = failure (IndexFailure n)+ | otherwise = go xs n+ where+ go [] _ = failure (IndexFailure n)+ go (x:_) 0 = return x+ go (_:xx) i = go xx (i-1)+++data ReadFailure = ReadFailure String deriving (Show,Typeable)+instance Exception ReadFailure where+ fromException = safeExceptionFromException+ toException = safeExceptionToException++read :: (Read a, MonadFailure ReadFailure m) => String -> m a+read s = case [x | (x,t) <- reads s, ("","") <- lex t] of+ [x] -> return x+ _ -> failure (ReadFailure s)++data LookupFailure a = LookupFailure a deriving (Show,Typeable)+instance (Typeable a, Show a) => Exception (LookupFailure a) where+ fromException = safeExceptionFromException+ toException = safeExceptionToException++-- |+-- > lookupJust key = fromJust . lookup key+lookup :: (Eq a, MonadFailure (LookupFailure a) m) => a -> [(a,b)] -> m b+lookup key = maybe (failure (LookupFailure key)) return . Prelude.lookup key+++#ifdef CME++-- Encoding the exception hierarchy in Throws++instance Throws TailFailure (Caught SafeException l)+instance Throws HeadFailure (Caught SafeException l)+instance Throws InitFailure (Caught SafeException l)+instance Throws LastFailure (Caught SafeException l)+instance Throws MinimumFailure (Caught SafeException l)+instance Throws MaximumFailure (Caught SafeException l)+instance Throws Foldr1Failure (Caught SafeException l)+instance Throws Foldl1Failure (Caught SafeException l)+instance Throws FromJustFailure (Caught SafeException l)+instance Throws IndexFailure (Caught SafeException l)+instance Throws ReadFailure (Caught SafeException l)+instance (Typeable a, Show a) => Throws (LookupFailure a) (Caught SafeException l)++#endif
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ safe-failure.cabal view
@@ -0,0 +1,43 @@+Name: safe-failure+Build-Type: Simple+Cabal-Version: >= 1.2+Version: 0.1+License: BSD3+License-File: LICENSE+Copyright: 2007-8, Neil Mitchell+Maintainer: pepeiborra@gmail.com+Author: Neil Mitchell, Jose Iborra (2009), Michael Snoyman (2009)+Homepage: http://www-users.cs.york.ac.uk/~ndm/safe/+Category: Unclassified+Synopsis: Library for safe functions+Description:+ Partial functions from the base library, such as @head@ and @!!@, modified+ to fail in a @MonadFailure@ monad.+ + These functions can be used to reduce the number of unsafe pattern matches in+ your code.++Flag cme+ description: build with special support for control-monad-exception+ default: True++Flag extensibleExceptions+ description: Use extensible-exception package+ default: False++Library+ buildable: True+ build-depends: control-monad-failure+ if flag(extensibleExceptions)+ build-depends:+ extensible-exceptions >= 0.1 && <0.2,+ base >= 3.0 && <4+ else+ build-depends:+ base >= 4 && < 5+ exposed-modules: + Safe.Failure+ ghc-options: -Wall+ if flag(cme)+ build-depends: control-monad-exception+ cpp-options: -DCME