{-# OPTIONS_HADDOCK prune, ignore-exports #-} module Data.Nutrition.Macros ( Macros () , newMacros , prot , carb , fat ) where import Control.Category type Percent = Float type Protein = Percent type Carb = Percent type Fat = Percent -- | The macro nutrients are @Protein@, @Carbohydrate@ and @Fat@. They -- are stored within a triple that is called 'Macros'. data Macros = Macros (Protein, Carb, Fat) -- | 'prot', 'carb' and 'fat' are functions that return the percent of -- that macro nutrient. They are basically getters of the 'Macros' -- data. prot, fat, carb :: Macros -> Percent prot (Macros (p, _, _)) = p carb (Macros (_, c, _)) = c fat (Macros (_, _, f)) = f -- | 'newMacros' is a smart constructor to 'Macros'. It checks, -- whether the sum of the percentages is equal or below -- 100%. Otherwise it does not construct a 'Macros' value. newMacros :: (Protein, Carb, Fat) -> Macros newMacros (p, c, f) | (p + c + f) <= 100 = Macros (p, c, f) | otherwise = error \$ "macro definition exeeds 100%" -- instance Num Macros where -- m1 + m2 = newMacros \$ percentualDo (+) (prot m1, carb m1, fat m1) (prot m2, carb m2, fat m2) -- m1 - m2 = newMacros \$ percentualDo (-) (prot m1, carb m1, fat m1) (prot m2, carb m2, fat m2) -- (*) = error "this operation isn't defined on macros" -- percentualDo op (p1, c1, f1) (p2, c2, f2) -- = (p, c, f) -- where sum1 = p1 + c1 + f1 -- sum2 = p2 + c2 + f2 -- percentCalc op sum1 sum2 v1 v2 -- = (v1 * 100.0 / sum1) `op` (v2 * 100.0 / sum2) / 2 -- p = percentCalc op sum1 sum2 p1 p2 -- c = percentCalc op sum1 sum2 c1 c2 -- f = percentCalc op sum1 sum2 f1 f2