I attempted the Business Rules Kata. Here's a video overview.However, I am not confident that going functional is a good strategy for the following objective:How can you tame these wild business rules? How can you build a system  that will be flexible enough to handle both the complexity and the  need for change? And how can you do it without condemning yourself to  years and years of mindless support?Is there an alternative FP approach that satisfies the objective stated above?module PaymentSystem(*Types*)type ProductId =          ProductId of stringtype MemberId =           MemberId  of stringtype Email =              Email     of stringtype Agent =              Agenttype RoyaltyDepartment =  RoyaltyDepartmenttype PackingSlip = {    MemberId:MemberId    ProductId:ProductId}type PhysicalProducts =    | Book    | Video    | Othertype MembershipType =    | Membership of MemberId    | Upgrade    of MemberIdtype PaymentFor =    | PhysicalProduct of PhysicalProducts * PackingSlip    | Membership      of MembershipTypetype PackingSlipOptions =    | PackingSlip       of PackingSlip    | DuplicateSlips    of PackingSlip    | WithFirstAidVideo of PackingSliptype PaymentResponse =    | PackingSlip        of PackingSlipOptions    | ActivateMembership of MemberId    | UpgradeMembership  of MemberId    | EmailOwner         of MembershipType    | CommissionPayment  of Agent(*Functions*)let publish payload = ()       // Stublet getAgent productId = Agent // Stublet respondTo (payment:PaymentFor) =    match payment with    | PhysicalProduct     (kind , packingSlip) ->         publish (CommissionPayment (getAgent packingSlip.ProductId))        match kind with        | Book  -> publish (DuplicateSlips    packingSlip)        | Video -> publish (WithFirstAidVideo packingSlip)        | Other -> publish packingSlip    | Membership kind ->        publish(EmailOwner kind)        match kind with        | MembershipType.Membership memberId -> publish(ActivateMembership memberId)        | MembershipType.Upgrade    memberId -> publish(UpgradeMembership  memberId)    
Wild and changing business rules implemented with functional programming
f#
The original requirementHow can you tame these wild business rules? How can you build a system that will be flexible enough to handle both the complexity and the need for change? And how can you do it without condemning yourself to years and years of mindless support?seems, to me, to insinuate some sort of generic rules engine. This is, I believe, a red herring. The problem with rules engines, in my experience, is that the selling point is always that 'business users' can maintain them without involving developers.This is a pipe dream, because if business rules can be arbitrarily complex, you're going to need a rules engine that can handle all of this complexity. In other words, you're going to need a programming language, and then it becomes too technical for business users.This is called the inner platform effect and is, in my opinion, best avoided.So you might as well use a programming language to implement the rules, and I see no reason you can't use a functional language like F#.Here's a sketch of some of the rules. Like in the real world, some of the rules are vaguely defined, so I wasn't sure how to interpret them...type Membership = Basic | Goldtype Good =| PhysicalProduct of string| Book of string| Video of string| Membership of Membership| Upgradetype Command =| Slip of string * (Good list)| Activate of Membership| Upgrade| PayAgentThese are simply some types, but given these types, you can implement various business rules, e.g.// Good -> Command listlet slipForShipping = function| PhysicalProduct name| Book name| Video name -> [Slip (Shipping, [PhysicalProduct name])] | _ -> []// Good -> Command listlet slipForRoyalty = function| Book name -> [Slip (Royalty, [Book name])]| _ -> []// Good -> Command listlet activate = function | Membership x -> [Activate x] | _ -> []// Good -> Command listlet upgrade = function | Good.Upgrade -> [Upgrade] | _ -> []You'll notice that all these rules have the same type, which means that you can collect all of them:// ('a -> 'b list) list -> 'a -> 'b listlet handle handlers good = handlers |> List.collect (fun h -> h good)// Good -> Command list    let handleAll = handle [slipForShipping; slipForRoyalty; activate; upgrade]Example:> handleAll (Book The Annotated Turing);;val it : Command list =  [Slip (Shipping,[PhysicalProduct The Annotated Turing]);   Slip (Royalty,[Book The Annotated Turing])]As far as I can tell, this would be fairly maintainable, because if you need to add a new rule, you'll have to add a new function, and add that function to handleAll.