F# Domain Modeling: IRS Tax Form 8889

I’ve discovered that IRS tax forms can serve as mind-numbing code katas.

I attempted to domain model HSA Form 8889 in F#.

The code can be found on my GitHub account.

Language

namespace HSATaxForm_2020

open System

module rec Language =

    module InEligible =

        type Coverage = Medicare | TriCare | TriCareLife

    type Amount                   = float
    type IsSelfEmployed           = bool
    type IsEmployeesFiftyOrFewer  = bool
    type NoOtherCoverageCompliant = bool
    type HadSameCoverage          = bool
    type Plans                    = string seq
    type AdditionalPercentageTax  = float

    type IsDead          = bool
    type IsDisabled      = bool
    type Turned65        = bool

    module Contributions =

        module AdditionalAmount =

            type Conditions = {
                IsFiftyFivePlus : bool
                IsMarried       : bool
                FamilyCoverageBySelfOrSpouse : bool
            }

        type Applicable = Amount
        module InExcess = type WithdrawnByDueDate = Amount

    module ThisYear =

        module Self =

            module Contributions =

                type Applicable = Amount

    module TaxYear =

        type MonthsCovered = int

        module EndOf = type IsUnder55     = bool
        module Self  = type Contributions = float

    module HDHP =

        type Plan     = string
        type IsSelf   = bool
        type IsSpouse = bool

    module MSA = 

        module Self     = type Contribution              = Amount
        module Employer = type Contribution              = Amount
        module Family   = type TowardsSpouseContribution = Amount

    module HSA =

        type Account = { Name : string }

        type Distribution  = { 
            Account   : Account
            Amount    : float 
            Timestamp : DateTime
          }

        type Distributions = Distribution seq

        type RollOver = { 
            Distribution : Distribution
            Target       : Account
        }
        
        type ExceptionsToPercentageTax = {
            IsDead     : bool
            IsDisabled : bool
            Turned65   : bool
        }

        type RollOvers = RollOver seq

        type HDHPCoverage  = SelfOnly | Family
        type QualifiedFundingDistributions = Amount
        type EmployerContributions         = Amount
        type MedicalExpensesPaidByDistribution  = { Distribution : Distribution }
        type MedicalExpensesPaidByDistributions = MedicalExpensesPaidByDistribution seq

        type ContributionLimit = Amount

Shared

namespace HSATaxForm_2020.Shared

open HSATaxForm_2020.Language

module Operations =

    module Calculate =

        type LesserOf = float -> float -> float

    module Eligibility =

        type HasFirstDayEveryMonth = HDHP.Plan -> bool
        type IsMSAQualified        = IsSelfEmployed -> IsEmployeesFiftyOrFewer -> bool

    module HDHP =

        module Family =

            module Spouse =

                type SeparateHSA = bool

            type BySelfOrSpouse = HDHP.IsSelf -> HDHP.IsSpouse -> bool

Part 1

namespace HSATaxForm_2020

open Language
open Language.HSA

open HSATaxForm_2020.Shared.Operations

module Part1 =

    module Line =

        type One      = HDHPCoverage
        type Two      = TaxYear.Self.Contributions -> ThisYear.Self.Contributions.Applicable -> Amount
        type Three    = TaxYear.EndOf.IsUnder55    -> Eligibility.HasFirstDayEveryMonth -> NoOtherCoverageCompliant -> HadSameCoverage -> Amount
        type Four     = MSA.Self.Contribution -> MSA.Employer.Contribution -> HDHP.Family.BySelfOrSpouse -> MSA.Family.TowardsSpouseContribution -> Amount
        type Five     = Four -> Three -> Amount
        type Six      = Five -> HDHP.Family.Spouse.SeparateHSA -> Amount
        type Seven    = Contributions.AdditionalAmount.Conditions -> Amount -> Amount
        type Eight    = Six -> Seven -> Amount
        type Nine     = EmployerContributions
        type Ten      = QualifiedFundingDistributions
        type Eleven   = Nine   -> Ten   -> Amount
        type Twelve   = Eleven -> Eight -> Amount
        type Thirteen = Two -> Twelve -> Calculate.LesserOf -> Amount

Part 2

namespace HSATaxForm_2020

open Language
open Language.HSA

module Part2 =

    module Line =

        type Fourteen_A  = Distributions -> Amount
        type Fourteen_B  = Distributions -> RollOvers -> Contributions.InExcess.WithdrawnByDueDate -> Amount
        type Fourteen_C  = Fourteen_B -> Fourteen_A -> Amount
        type Fifteen     = MedicalExpensesPaidByDistributions -> Amount
        type Sixteen     = Fourteen_C -> Fifteen -> Amount

        type Seventeen_A = ExceptionsToPercentageTax -> bool
        type Seventeen_B = Distributions -> AdditionalPercentageTax -> Amount

Part 3

namespace HSATaxForm_2020

open Language

module Part3 =

    module Line =

        type Eighteen   = HSA.ContributionLimit -> TaxYear.MonthsCovered -> Amount
        type Nineteen   = Part1.Line.Ten
        type Tweenty    = Eighteen -> Nineteen -> Amount
        type TweentyOne = Tweenty -> AdditionalPercentageTax -> Amount

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: