Rohit Sharma
Rohit Sharma

Reputation: 6500

How do i specify the min bound of an Integer

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

Answers (1)

Jon Purdy
Jon Purdy

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

Related Questions