catala icon indicating copy to clipboard operation
catala copied to clipboard

Implementation of Section 1001 of the US Tax Code

Open denismerigoux opened this issue 3 years ago • 5 comments

denismerigoux avatar Feb 17 '22 13:02 denismerigoux

@denismerigoux

After trying my hand at this, I'm curious how you want to handle the pattern of exceptional subsections requiring additional or specialized information. If the scope declaration/function signature only has input fields that require information sufficient to handle the default case, you may not be able to handle the exceptions or determine whether a given condition is met. On the other hand, if you ask for all of the possible information you might need for the whole section, some signatures will get quite large; without a way to express relationships between arguments large sets of arguments will likely be sources of errors.

The default rule for 1001 just needs to know the fair market value of property received, and the amount of money received. However, (b)(2) is an exception that wants to know about real property taxes under 164, and (e) is an exception that wants to know about a potential term interest to determine whether the exception applies. If 1001 is done as a single scope, the inputs would need to be something like

fmv_property_received content money
money_received content money
property_tax_reimbursed_164 content option<money>
property_tax_paid_by_purchaser_164 content option<money>
term_of_years content option<some struct or enum>

Not having option and requiring a $0 input is against the grain for functional programming, but may still be what you want to do (which is fine). The 1015 example has a match on Some/None, but the file doesn't type check, and option doesn't appear in the syntax cheat sheet, so maybe this was a feature that got axed? Alternatively, you could break up the subsections into their own scopes that take the correct set of inputs, though this means that the caller would have to know the correct subsection. This might not be so bad; it seems like the different type signatures would provide some safety, and the actual statutory implementation seems to represent something more like a private API than a public one. Taxpayers aren't going to be looking at the US Code when determining their tax liability, and in the same vein as our discussion about the 1040, something like a public API implemented on top of the statutory stuff that directly addresses the needs of practitioners might be in line with the layered architecture theme.

You could also create an enum that serves as the argument, though that does move closer to "just use a programming language", and wouldn't handle cases in which there's overlap (if a transaction has characteristics of exception 1 and exception 2).

Lastly, is there a means of calling external resources? Certain parts of the code require retrieval of a value from something like an actuarial or depreciation table (these are supplied by the government) or adjustments for inflation which presumably would need to be part of the ocaml codebase. For test cases, the most common ones are probably the marginal rate schedule, and MACRS depreciation tables.

ammkrn avatar Feb 24 '22 18:02 ammkrn

Hi Chris, let me answer your questions.

After trying my hand at this, I'm curious how you want to handle the pattern of exceptional subsections requiring additional or specialized information. If the scope declaration/function signature only has input fields that require information sufficient to handle the default case, you may not be able to handle the exceptions or determine whether a given condition is met. On the other hand, if you ask for all of the possible information you might need for the whole section, some signatures will get quite large; without a way to express relationships between arguments large sets of arguments will likely be sources of errors.

This is a relevant remark, that shows that you have quite some experience translating law into code and a deep understanding of it. What you are talking about is a known problem, related to https://github.com/CatalaLang/catala/issues/102. There are several mitigation strategies: first, mark your scope's input as context instead of input, and provide a default definition for those inputs inside the scope when such a default definition makes sense. Second, give more structure to your inputs by using enumerations that capture the relationship between all the pieces of the input. Ultimately, you would want a completely dependently typed language to capture accurately real-world relationships between the inputs in complex pieces of law; unfortunately this would add A LOT of complexity to Catala and we don't plan to turn Catala into a dependently-typed language :)

The default rule for 1001 just needs to know the fair market value of property received, and the amount of money received. However, (b)(2) is an exception that wants to know about real property taxes under 164, and (e) is an exception that wants to know about a potential term interest to determine whether the exception applies. If 1001 is done as a single scope, the inputs would need to be something like

fmv_property_received content money
money_received content money
property_tax_reimbursed_164 content option<money>
property_tax_paid_by_purchaser_164 content option<money>
term_of_years content option<some struct or enum>

Not having option and requiring a $0 input is against the grain for functional programming, but may still be what you want to do (which is fine). The 1015 example has a match on Some/None, but the file doesn't type check, and option doesn't appear in the syntax cheat sheet, so maybe this was a feature that got axed? Alternatively, you could break up the subsections into their own scopes that take the correct set of inputs, though this means that the caller would have to know the correct subsection. This might not be so bad; it seems like the different type signatures would provide some safety, and the actual statutory implementation seems to represent something more like a private API than a public one. Taxpayers aren't going to be looking at the US Code when determining their tax liability, and in the same vein as our discussion about the 1040, something like a public API implemented on top of the statutory stuff that directly addresses the needs of practitioners might be in line with the layered architecture theme.

You could also create an enum that serves as the argument, though that does move closer to "just use a programming language", and wouldn't handle cases in which there's overlap (if a transaction has characteristics of exception 1 and exception 2).

I guess you thought of the exact same mitigations strategies as me and brilliantly described them on the example at hand :)

Lastly, is there a means of calling external resources? Certain parts of the code require retrieval of a value from something like an actuarial or depreciation table (these are supplied by the government) or adjustments for inflation which presumably would need to be part of the ocaml codebase. For test cases, the most common ones are probably the marginal rate schedule, and MACRS depreciation tables.

Not yet, but support for this planned in https://github.com/CatalaLang/catala/issues/89.

denismerigoux avatar Feb 25 '22 13:02 denismerigoux

And yeah the Section 1015 example is an old prototype that we did not retrofit to the current version of Catala, we should create an issue for that.

denismerigoux avatar Feb 25 '22 13:02 denismerigoux

I pushed a relevant commit on this branch(the first is just a typo fix). After reworking this a couple of times and thinking a lot about how this will intersect with users and other code sections, I have much more articulable positions on some of the issues that were brought up earlier. I'll write them down over the weekend and maybe we can discuss them if there's a meeting next week.

ammkrn avatar Feb 25 '22 23:02 ammkrn

Thanks @ammkrn! I think you can move your progress on 1011 into this branch as well, so that we'll merge 1001 and 1011 together.

denismerigoux avatar Feb 28 '22 10:02 denismerigoux

Closing this as it has become stale.

denismerigoux avatar Sep 02 '22 14:09 denismerigoux