packages feed

safe (empty) → 0.2

raw patch · 4 files changed

+307/−0 lines, 4 filesdep +basesetup-changed

Dependencies added: base

Files

+ 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.hs view
@@ -0,0 +1,254 @@++{- |+Module      :  Safe+Copyright   :  (c) Neil Mitchell 2007-2008+License     :  BSD3++Maintainer  :  http://www.cs.york.ac.uk/~ndm/+Stability   :  in-progress+Portability :  portable++A library for safe functions, based on standard functions that may crash.+For more details see <http://www-users.cs.york.ac.uk/~ndm/safe/>++In general, each unsafe function has up to 4 forms.+Since 'tail' has all the possible forms, it is fully documented.+The others all follow the same pattern.+++* @Note@, takes an extra argument which supplements the error message, 'tailNote'++* @Def@, take an extra argument to give when a crash would otherwise happen, 'tailDef'++* @May@, wraps the result in a Maybe, 'tailMay'++* @Safe@, returns a default type if possible, 'tailSafe'++This library also introduces three brand new functions:++* 'at' - synonym for @(!!)@++* 'lookupJust' - defined as @lookupJust k = fromJust . lookup k@++* 'abort' - same as @error@, but different intended meaning++-}++module Safe(+    tailDef, tailMay, tailNote, tailSafe,+    initDef, initMay, initNote, initSafe,+    headDef, headMay, headNote,+    lastDef, lastMay, lastNote,+    minimumDef, minimumMay, minimumNote,+    maximumDef, maximumMay, maximumNote,+    foldr1Def, foldr1May, foldr1Note,+    foldl1Def, foldl1May, foldl1Note,+    fromJustDef, fromJustNote,+    assertNote,+    at, atDef, atMay, atNote,+    readDef, readMay, readNote,+    lookupJust, lookupJustDef, lookupJustNote,+    abort+    ) where+++import Data.Maybe++{-# PARTIAL tailNote, initNote, headNote, lastNote, minimumNote, maximumNote #-}+{-# PARTIAL foldr1Note, foldl1Note, fromJustNote, assertNote, at, atNote, readNote #-}+{-# PARTIAL lookupJustNote, lookupJust #-}+++liftDef :: (a -> b) -> (a -> Bool) -> b -> (a -> b)+liftDef func test def val = if test val then def else func val++liftMay :: (a -> b) -> (a -> Bool) -> (a -> Maybe b)+liftMay func test val = if test val then Nothing else Just $ func val++liftNote :: (a -> b) -> (a -> Bool) -> String -> String -> (a -> b)+liftNote func test caller note val =+    if test val+    then error $ "Pattern match failure, " ++ caller ++ ", " ++ note+    else func val++liftSafe :: (a -> a) -> (a -> Bool) -> (a -> a)+liftSafe func test val = if test val then val else func val+++-- |+-- > tailDef [12] [] = [12]+-- > tailDef [12] [1,3,4] = [3,4]+tailDef  :: [a] -> [a] -> [a]+tailDef  = liftDef  tail null++-- |+-- > tailMay [] = Nothing+-- > tailMay [1,3,4] = Just [3,4]+tailMay  :: [a] -> Maybe [a]+tailMay  = liftMay  tail null++-- |+-- > tail "help me" [] = error "Pattern match failure, tail [], help me"+-- > tail "help me" [1,3,4] = [3,4]+tailNote :: String -> [a] -> [a]+tailNote = liftNote tail null "tail []"++-- |+-- > tailSafe [] = []+-- > tailSafe [1,3,4] = [3,4]+tailSafe :: [a] -> [a]+tailSafe = liftSafe tail null+++initDef  :: [a] -> [a] -> [a]+initDef  = liftDef  init null++initMay  :: [a] -> Maybe [a]+initMay  = liftMay  init null++initNote :: String -> [a] -> [a]+initNote = liftNote init null "init []"++initSafe :: [a] -> [a]+initSafe = liftSafe init null++++headDef  :: a -> [a] -> a+headDef  = liftDef  head null++headMay  :: [a] -> Maybe a+headMay  = liftMay  head null++headNote :: String -> [a] -> a+headNote = liftNote head null "head []"+++lastDef  :: a -> [a] -> a+lastDef  = liftDef  last null++lastMay  :: [a] -> Maybe a+lastMay  = liftMay  last null++lastNote :: String -> [a] -> a+lastNote = liftNote last null "last []"++++minimumDef  :: Ord a => a -> [a] -> a+minimumDef  = liftDef  minimum null++minimumMay  :: Ord a => [a] -> Maybe a+minimumMay  = liftMay  minimum null++minimumNote :: Ord a => String -> [a] -> a+minimumNote = liftNote minimum null "minimum []"+++maximumDef  :: Ord a => a -> [a] -> a+maximumDef  = liftDef  maximum null++maximumMay  :: Ord a => [a] -> Maybe a+maximumMay  = liftMay  maximum null++maximumNote :: Ord a => String -> [a] -> a+maximumNote = liftNote maximum null "maximum []"++++foldr1Def  :: a -> (a -> a -> a) -> [a] -> a+foldr1Def def f = liftDef (foldr1 f) null def++foldr1May  :: (a -> a -> a) -> [a] -> Maybe a+foldr1May f = liftMay (foldr1 f) null++foldr1Note :: String -> (a -> a -> a) -> [a] -> a+foldr1Note note f = liftNote (foldr1 f) null "foldr1 []" note+++foldl1Def  :: a -> (a -> a -> a) -> [a] -> a+foldl1Def def f = liftDef (foldl1 f) null def++foldl1May  :: (a -> a -> a) -> [a] -> Maybe a+foldl1May f = liftMay (foldl1 f) null++foldl1Note :: String -> (a -> a -> a) -> [a] -> a+foldl1Note note f = liftNote (foldl1 f) null "foldl1 []" note+++-- | See fromMaybe+fromJustDef :: a -> Maybe a -> a+fromJustDef  = liftDef fromJust isNothing++fromJustNote :: String -> Maybe a -> a+fromJustNote = liftNote fromJust isNothing "fromJust Nothing"++++assertNote :: String -> Bool -> a -> a+assertNote msg False val = error $ "assertion failed, " ++ msg+assertNote msg True  val = val++++-- | Same as @(!!)@, but better error message+at :: [a] -> Int -> a+at = atNote "called by at"++atDef :: a -> [a] -> Int -> a+atDef def x n = fromMaybe def (atMay x n)++atMay :: [a] -> Int -> Maybe a+atMay xs n | n < 0 = Nothing+atMay [] _ = Nothing+atMay (x:_) 0 = Just x+atMay (_:xs) n = atMay xs (n-1)++atNote :: String -> [a] -> Int -> a+atNote msg _ n | n < 0 = error $ "Safe.at: negative index, " ++ msg+atNote msg xs n = f xs n+    where+        f [] i = error $ "Safe.at: index too large, index=" ++ show n ++ ", length=" ++ show (n-i) ++ ", " ++ msg+        f (x:_) 0 = x+        f (_:xs) i = f xs (i-1)++++readDef :: Read a => a -> String -> a+readDef def s = fromMaybe def (readMay s)++readMay :: Read a => String -> Maybe a+readMay s = case [x | (x,t) <- reads s, ("","") <- lex t] of+                [x] -> Just x+                _ -> Nothing++readNote :: Read a => String -> String -> a+readNote msg s = case [x | (x,t) <- reads s, ("","") <- lex t] of+                     [x] -> x+                     []  -> error $ "Prelude.read: no parse, " ++ msg ++ ", on " ++ prefix+                     _   -> error $ "Prelude.read: ambiguous parse, " ++ msg ++ ", on " ++ prefix+    where+        prefix = '\"' : a ++ if null b then "\"" else "..."+            where (a,b) = splitAt 10 s+++-- |+-- > lookupJust key = fromJust . lookup key+lookupJust :: Eq a => a -> [(a,b)] -> b+lookupJust key = fromJustNote "lookupJust, item not found" . lookup key++lookupJustDef :: Eq a => b -> a -> [(a,b)] -> b+lookupJustDef def key lst = fromMaybe def (lookup key lst)++lookupJustNote :: Eq a => String -> a -> [(a,b)] -> b+lookupJustNote msg key lst = case lookup key lst of+                                 Nothing -> error $ "Safe.lookupJust: element not found, " ++ msg+                                 Just x -> x++++-- | Exactly the same as @error@. Use this for instances where the program+--   has decided to exit because of invalid user input, or the user pressed+--   quit etc. This allows @error@ to be reserved for genuine coding mistakes.+abort :: String -> a+abort = error
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ safe.cabal view
@@ -0,0 +1,21 @@+Name:           safe+Build-Type:     Simple+Version:        0.2+License:        BSD3+License-File:   LICENSE+Copyright:      2007-8, Neil Mitchell+Maintainer:     ndmitchell@gmail.com+Author:         Neil Mitchell+Homepage:       http://www-users.cs.york.ac.uk/~ndm/safe/+Build-Depends:  base+Category:       Unclassified+Synopsis:       Library for safe (pattern match free) functions+Description:+    Partial functions from the base library, such as @head@ and @!!@, modified+    to return more descriptive error messages, programmer defined error messages,+    @Maybe@ wrapped results and default values.+    +    These functions can be used to reduce the number of unsafe pattern matches in+    your code.+Exposed-modules:+        Safe