I was wondering if there was anything else that can be done
Well, morally, no. You can either return a nullable value (Maybe UTCTime) or lie (read "1970-01-01 00:00:00 UTC" :: UTCTime) but you can't turn a DbNumber 1 :: DatabaseItem into a UTCTime both unconditionally and truthfully.
The good news is, if you hit on the right set of higher-order functions you don't need to. Maybe values are very easy to work with when you know the extra tools available in Data.Maybe.
Taking as a whole this set of functions related to dates—
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 mostRecent :: [DatabaseItem] -> UTCTime mostRecent dataBase = foldr max y ys where dates = filterDbDate dataBase y = head dates ys = tail dates We'll begin by throwing out isDbDate and extractUTCTime and writing the DatabaseItem -> Maybe UTCTime function you avoided.
dbDate :: DatabaseItem -> Maybe UTCTime dbDate (DbDate utc) = Just etc dbDate _ = Nothing Now pulling from Data.Maybe, we'll replace filterDbDate with an equivalent code fragment that utilizes mapMaybe.
-- filterDbDate :: [DatabaseItem] -> [UTCTime] -- filterDbDate db = mapMaybe dbDate db We can use that definition in mostRecent, a function from the standard Prelude, and point free style to achieve a one liner that more than just being clever, emphasizes the power of abstraction in producing concise code that will be instantly comprehensible to other Haskell programmers.
mostRecent :: [DatabaseItem] -> UTCTime mostRecent = maximum . mapMaybe dbDate mostRecent still commits the sin of using a partial function though, maximum throws an exception (much like your use of head and tail did before) when the filtered list is empty. Until such time as partial functions are excised from base (and O, do we all lust for and fear such a tumultuous day) you should familiarize yourself with the safe package, which has no dependencies besides base, and provides many alternatives to the partial functions we all know and love.
import Safe.Foldable (maximumMay) mostRecent :: [DatabaseItem] -> Maybe UTCTime mostRecent = maximumMay . mapMaybe dbDate