{-# OPTIONS_GHC -XScopedTypeVariables #-} ----------------------------------------------------------------------------- -- -- Module : Base.MyMissing -- Copyright : Juergen Nicklisch-Franken -- License : LGPL -- -- Maintainer : maintainer@leksah.org -- Stability : provisional -- Portability : portabel -- -- | Module for missing base functions -- ------------------------------------------------------------------------------ module Base.MyMissing ( allOf , forceJust , forceHead , splitString , replace , nonEmptyLines , trim , insertAt , myCast , maybeRead ) where import Data.List (find,unfoldr) import Data.Maybe (listToMaybe, isJust) import Data.Char (isSpace) import Data.Typeable (cast, Typeable(..), Typeable) -- | remove leading and trailing spaces trim :: String -> String trim = f . f where f = reverse . dropWhile isSpace nonEmptyLines :: String -> [String] nonEmptyLines = filter (\line -> isJust $ find (not . isSpace) line) . lines allOf :: forall alpha. (Bounded alpha, Enum alpha) => [alpha] allOf = map toEnum [fromEnum (minBound :: alpha) .. fromEnum (maxBound :: alpha)] -- --------------------------------------------------------------------- -- Convenience methods with error handling -- forceJust :: Maybe alpha -> String -> alpha forceJust mb str = case mb of Nothing -> error str Just it -> it -- --------------------------------------------------------------------- -- Convenience methods with error handling -- forceHead :: [alpha] -> String -> alpha forceHead (h:_) str = h forceHead [] str = error str -- --------------------------------------------------------------------- -- Splitting a string into parts based on a token delimiter -- splitString :: Eq a => a -> [a] -> [[a]] splitString = unfoldr . split' split' :: Eq a => a -> [a] -> Maybe ([a], [a]) split' c l | null l = Nothing | otherwise = Just (h, drop 1 t) where (h, t) = span (/=c) l -- --------------------------------------------------------------------- -- Simple replacement -- replace :: Eq a => [a] -> [a] -> [a] -> [a] replace _ _ [] = [] replace from to xs@(a:as) = if isPrefixOf from xs then to ++ replace from to (drop (length from) xs) else a : replace from to as where isPrefixOf as bs = and $ zipWith (== ) as bs -- --------------------------------------------------------------------- -- Insert in a list at index -- insertAt :: Int -> a -> [a] -> [a] insertAt i e l | i < 0 = e : l | i >= length l = l ++ [e] | otherwise = let (start,end) = splitAt i l in start ++ (e : end) -- | The type-safe cast operation myCast :: forall a b . (Typeable a, Typeable b) => String -> a -> b myCast errorString x = case cast x of Just x' -> x' Nothing -> error $ errorString ++ ". Cast error inputType: " ++ show (typeOf x) ++ " outputType: " ++ show (typeOf (undefined :: a)) -- | a read which may fail maybeRead :: Read alpha => String -> Maybe alpha maybeRead = listToMaybe . map fst . filter (null . snd) . reads