-- Apply a pricing procedure = a list of percentual or absolute additions -- forwards ("compute") -- and backwards ("resolve" - which is the point here). -- Each condition is a linear function on any of the formerly computed, -- intermediate terms, so a condition is a function [a] -> a percent p x = p * x / 100 -- Need a data type for conditions, -- in order to distinguish absolute from relative conditions data Condition a = RelativeCondition { apply :: a } | AbsoluteCondition { apply :: a } -- predicate function for detecting relative types isRelative :: Condition a -> Bool isRelative( RelativeCondition _ ) = True isRelative( _ ) = False condRel p = RelativeCondition (\ x -> percent p ( last x ) ) condRelBase p = RelativeCondition (\ x -> percent p ( head x ) ) condAbs q = AbsoluteCondition (\ x -> q ) -- How to compute a scheme: -- Apply functions successively, starting with base price compute scheme base = last ( foldl (\ x f -> x ++ [ last x + apply f x ] ) [ base ] scheme ) --- Reduced scheme consists only of the relative conditions reduced scheme = filter isRelative scheme -- How to resolve a scheme resolve scheme result = ( result - compute scheme 0 ) / compute (reduced scheme) 1 -- A sample calculation scheme scheme = [ condAbs 10.00, condRel 5.00, condRelBase 3.25, condAbs 20.00, condRel 3.00, condRelBase 2.00, condRel 7.00, condAbs 10.00 ] -- Test (should reproduce the input (100) ) main = do print( resolve scheme ( compute scheme 100 ) )