Reputation: 6500
I am trying to solve an exercise question from the Haskell Book and wondering what minimum value should I specify in the start accumulator so I can find Max of DBNumber using foldr?
I can't specify minBound::Integer as there is no lower bound. I can probably find this by other means but wondering if i can use foldr as below?
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",
DbNumber -9002,
DbNumber -109001,
DbDate (UTCTime (fromGregorian 1921 5 1) (secondsToDiffTime 34123))]
maxDbNumber xs = foldr (\x y -> case x of
DbNumber z | z > y -> z
otherwise -> y) (minBound::Integer) xs
Upvotes: 1
Views: 350
Reputation: 55069
Not terribly elegant, but not complicated either—you could use the fact that Nothing < Just x
for any x
:
foldr (\x acc -> case x of
DbNumber z -> Just z `max` acc
_ -> acc) Nothing xs
This could be written a little more compactly by defining a function to extract the number if present:
fromDbNumber :: DatabaseItem -> Maybe Integer
fromDbNumber (DbNumber z) = Just z
fromDbNumber _ = Nothing
maxDbNumber = foldr (max . fromDbNumber) Nothing
The point-free max . fromDbNumber
is derived like so:
-- Original:
\x acc -> max (fromDbNumber x) acc
-- Eta-reduce:
\x -> max (fromDbNumber x)
-- Definition of ‘(.)’:
max . fromDbNumber
This changes the result to Maybe Integer
, of course, but this is appropriate: you need to do something to handle the case where there is no maximum, even if it’s just returning a default value.
Upvotes: 2