First of: sorry for the ambigous question title... Second: I am a complete beginner...
I have a very simple data type called Task. A Task had a price, an amount and a unit. The unit can be days or hours.
I want to calculate the total amount and total price for a list of Tasks. For the price there is no issue, I multiply each price with the amount for the given task and it adds up. But for the amount I am stuck.
I cannot easely fold a list of hours and days. Say I have a task with 1 hour and one with 1 day, both of them have an amount of 1, but the total should be in one unit. I chose 'hour' as the base unit.
So to recap, this is my type:
-- data --
-- the task is parsed from json, but I would like the `unit` type to be
-- custom like `Hour | Day` instead of String. But that is an aeson issue?
data Task = {
amount :: Double,
price :: Double,
unit :: String
}
-- functions --
taskPrice :: Task -> Double
taskPrice t = fromIntegral (price t) * amount t
calcPrice :: [Task] -> Double
calcPrice [] = 0
calcPrice [x] = taskPrice x
calcPrice (x:xs) = foldl (\acc x -> acc + (taskPrice x)) (taskPrice x) xs
-- this version will add days and hours like they are equal...
calcInvoiceHours :: [Task] -> Double
calcInvoiceHours [] = 0
calcInvoiceHours [x] = amount x
calcInvoiceHours (x:xs) = foldl (\acc x -> acc + (amount x)) (amount x) xs
Every Task knows it's own type, but a switch case inside the pattern matching is not the way to go I guess... In some naive pseudo code I would write:
calcInvoiceHours :: [Task] -> Double
calcInvoiceHours [] = 0
calcInvoiceHours [x -> unit x === Hour] = amount x
calcInvoiceHours [x -> unit x === Day] = (amount x) * 8 -- work 8 hours a day
calcInvoiceHours (x:xs) = foldl (\acc x -> acc + (amount x)) (amount x)
I know this is wrong, but I do not know how to do it. I might be running before I can walk here, but it seems like such a simple task (no pun intended).
Thanks!
== UPDATE ==
I found a way! But if this is not the good way, I would be glad to hear how I can improve! Plus I am still searching to parse the strings 'hours' and 'days' to a concrete custome type Hour | Day from json.
taskHours :: Task -> Double
taskHours (Task _ amount _ unit)
| unit == "hours" = amount
| otherwise = amount * 8
calcInvoiceHours :: [Task] -> Double
calcInvoiceHours [] = 0
calcInvoiceHours [x] = taskHours x
calcInvoiceHours (x:xs) = foldl (\acc x -> acc + (taskHours x)) (taskHours x) xs