summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Joey Hess <joey@kitenet.net>2011-12-09 18:10:41 -0400
committerGravatar Joey Hess <joey@kitenet.net>2011-12-09 18:10:41 -0400
commit28699c95a7de284f07a5c0e34fb1755868301f3c (patch)
treeef6b372edf27c9cbb508169e7adf707dc25a84c6
parent95e748cbd4bb858a3b87621e60f5b43d53b50480 (diff)
some work on avoiding partial functions
There are still hundreds of places that use partial functions head, tail, init, and last.
-rw-r--r--Command/DropUnused.hs4
-rw-r--r--Git.hs18
-rw-r--r--Utility/BadPrelude.hs24
-rw-r--r--Utility/Misc.hs13
4 files changed, 45 insertions, 14 deletions
diff --git a/Command/DropUnused.hs b/Command/DropUnused.hs
index 3df9ab6c2..244f378d9 100644
--- a/Command/DropUnused.hs
+++ b/Command/DropUnused.hs
@@ -73,6 +73,6 @@ readUnusedLog prefix = do
then M.fromList . map parse . lines <$> liftIO (readFile f)
else return M.empty
where
- parse line = (num, fromJust $ readKey $ tail rest)
+ parse line = (num, fromJust $ readKey rest)
where
- (num, rest) = break (== ' ') line
+ (num, rest) = separate (== ' ') line
diff --git a/Git.hs b/Git.hs
index 5bdd4afd4..84153be5d 100644
--- a/Git.hs
+++ b/Git.hs
@@ -507,11 +507,7 @@ configStore s repo = do
configParse :: String -> M.Map String String
configParse s = M.fromList $ map pair $ lines s
where
- pair l = (key l, val l)
- key l = head $ keyval l
- val l = join sep $ drop 1 $ keyval l
- keyval l = split sep l :: [String]
- sep = "="
+ pair = separate (== '=')
{- Calculates a list of a repo's configured remotes, by parsing its config. -}
configRemotes :: Repo -> IO [Repo]
@@ -550,13 +546,11 @@ genRemote s repo = gen $ calcloc s
scpstyle v = ":" `isInfixOf` v && not ("//" `isInfixOf` v)
scptourl v = "ssh://" ++ host ++ slash dir
where
- bits = split ":" v
- host = head bits
- dir = join ":" $ drop 1 bits
- slash d | d == "" = "/~/" ++ dir
- | head d == '/' = dir
- | head d == '~' = '/':dir
- | otherwise = "/~/" ++ dir
+ (host, dir) = separate (== ':') v
+ slash d | d == "" = "/~/" ++ d
+ | "/" `isPrefixOf` d = d
+ | "~" `isPrefixOf` d = '/':d
+ | otherwise = "/~/" ++ d
{- Checks if a string from git config is a true value. -}
configTrue :: String -> Bool
diff --git a/Utility/BadPrelude.hs b/Utility/BadPrelude.hs
new file mode 100644
index 000000000..1bb70adfb
--- /dev/null
+++ b/Utility/BadPrelude.hs
@@ -0,0 +1,24 @@
+{- Some stuff from Prelude should not be used, as it tends to be a source
+ - of bugs.
+ -
+ - This exports functions that conflict with the prelude, which avoids
+ - them being accidentially used.
+ -}
+
+module Utility.BadPrelude where
+
+{- head is a partial function; head [] is an error -}
+head :: [a] -> a
+head = Prelude.head
+
+{- tail is also partial -}
+tail :: [a] -> a
+tail = Prelude.tail
+
+{- init too -}
+init :: [a] -> a
+init = Prelude.init
+
+{- last too -}
+last :: [a] -> a
+last = Prelude.last
diff --git a/Utility/Misc.hs b/Utility/Misc.hs
index 728598723..541e150b7 100644
--- a/Utility/Misc.hs
+++ b/Utility/Misc.hs
@@ -27,6 +27,19 @@ readMaybe s = case reads s of
((x,_):_) -> Just x
_ -> Nothing
+{- Like break, but the character matching the condition is not included
+ - in the second result list.
+ -
+ - separate (== ':') "foo:bar" = ("foo", "bar")
+ - separate (== ':') "foobar" = ("foo, "")
+ -}
+separate :: (a -> Bool) -> [a] -> ([a], [a])
+separate c l = unbreak $ break c l
+ where
+ unbreak r@(a, b)
+ | null b = r
+ | otherwise = (a, tail b)
+
{- Catches IO errors and returns a Bool -}
catchBoolIO :: IO Bool -> IO Bool
catchBoolIO a = catchDefaultIO a False