packages feed

billeksah-services-1.0.0: src/Base/MyMissing.hs

{-# 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