I am working through Chapter 10 of Haskell Programming from First Principles.
I've gotten the code to work, but I am uneasy about the fact that a few of my functions - namely, extractUTCTime and extractInteger - are not total functions. There is valid input for which those functions are bottom. I've added the code below, but I was wondering what strategies are available for making extractUTCTime and extractInteger safe. (One strategy that I do know of is changing the type signature of these functions so that they return a value of type Maybe: extractUTCTime :: DatabaseItem -> Maybe UTCTime. I was wondering if there was anything else that can be done).
import Data.Time
data DatabaseItem = DbString String | DbNumber Integer | DbDate UTCTime deriving (Eq, Ord, Show)
theDatabase :: [DatabaseItem]
theDatabase = [DbDate (UTCTime (fromGregorian 1911 5 1) (secondsToDiffTime 34123)), DbNumber 9001, DbString "Hello, world!", DbDate (UTCTime (fromGregorian 1921 5 1) (secondsToDiffTime 34123))]
filterDbDate :: [DatabaseItem] -> [UTCTime]
filterDbDate [] = []
filterDbDate dataBase = [extractUTCTime item | item <- dataBase, isDbDate item]
isDbDate :: DatabaseItem -> Bool
isDbDate (DbDate _) = True
isDbDate _ = False
extractUTCTime :: DatabaseItem -> UTCTime
extractUTCTime (DbDate utcData) = utcData
filterDbNumber :: [DatabaseItem] -> [Integer]
filterDbNumber [] = []
filterDbNumber dataBase = [extractInteger item | item <- dataBase, isDbNumber item]
extractInteger :: DatabaseItem -> Integer
extractInteger (DbNumber int) = int
isDbNumber :: DatabaseItem -> Bool
isDbNumber (DbNumber _) = True
isDbNumber _ = False
mostRecent :: [DatabaseItem] -> UTCTime
mostRecent dataBase = foldr max y ys
where dates = filterDbDate dataBase
y = head dates
ys = tail dates
sumDb :: [DatabaseItem] -> Integer
sumDb dataBase = foldr (+) 0 dbNumbers
where dbNumbers = filterDbNumber dataBase
avgDb :: [DatabaseItem] -> Double
avgDb dataBase = dividend / divisor
where dividend = fromIntegral $ sumDb dataBase
divisor = fromIntegral $ length $ filterDbNumber dataBase