LLScheme
LLScheme

Reputation: 105

Pattern match on data types

I have been struggling with this problem so far and was wondering if someone could point me in the right direction. This is my template so far:

data Expense = MkExpense Double String deriving (Eq,Ord)

mkExpense :: String -> Double -> Expense
mkExpense name amount = MkExpense amount name

instance Show Expense where
  show (MkExpense amount name) = name ++ ": " ++ show amount

data Delta = MkDelta Expense deriving (Eq,Ord)

instance Show Delta where
  show (MkDelta (MkExpense amount name)) = name ++ ": " ++ show amount

Right now I would like to sum over all the amounts of a list of the form (so in this case I would like to get 240):

[mkExpense "Alex" 40, mkExpense "Gert-Jan" 200]

which returns:

[Alex: 40.0,Gert-Jan: 200.0]

I know of the existence of foldr but I'm not sure how to pattern match properly against the "amounts" here. Normally I would use map to re-map to a single value list so I can use foldr freely, but it's not possible here because of my definition of the show-instance I presume.

Any help is appreciated.

Upvotes: 0

Views: 68

Answers (2)

chepner
chepner

Reputation: 532368

You don't need map; the function supplied to foldr can pattern-match directly.

> foldr (\(MkExpense v _) t -> v + t) 0 [mkExpense "Alex" 40, mkExpense "Gert-Jan" 200]
240.0

The same technique can be used for composing sum and map:

> sum $ map (\(MkExpense v _) -> v) [mkExpense "Alex" 40, mkExpense "Gert-Jan" 200]
240.0

Upvotes: 2

LLScheme
LLScheme

Reputation: 105

map (\(MkExpense amount name) -> amount) [mkExpense "Alex" 40, mkExpense "Gert-Jan" 200] does the trick, having "two constructors" where one flips the arguments caused the confusion as to why my map wasn't working.

Upvotes: 1

Related Questions