catala/examples/tutorial/tutorial_en.catala

170 lines
8.0 KiB
Plaintext
Raw Normal View History

2020-05-17 19:51:00 +03:00
@@The Catala language tutorial@@
Welcome to this tutorial, whose objective is to guide you through the features of the Catala language and trach you how to annotate a legislative text using the language. This document is addressed primarily to developers or people that have a programming background. It will use terms and jargon that might be unintelligible for lawyers in general.
@@Literate programming@@+
To begin writing a Catala program, you must start from the text of the legislative source that will justify the code that you will write. Concretely, that means copy-pasting the text of the law into a Catala source file and formatting it according so that Catala can understand it.
You can write any kind of plain text in Catala, and it will be printed as is in PDF or HTML output. Keep in mind however that one line in the source file corresponds to a paragraph in the output. Catala allows you to declare section or subsection headers as it is done here, but the fundamental division unit is the article. Let's analyse a fictional example that defines an income tax.
@Article 1@
The income tax for an individual is defined as a fixed percentage of the individual's income over a year.
/*
# This is a placeholder comment, the code for that article should go here
*/
We will now proceed to encode the algorithmic content of this article using the Catala language. To do that, we will intertwine short snippets of code between the sentences of the legislative text. Each snippet of code should be as short as possible and as close as possible to the actual sentence that justifies the code.
@@Defining a fictional income tax@@+
The content of article 1 uses a lot of implicit context : there exists an individual with an income, as well as an income tax that the individual has to pay each year. Even if this implicit context is not verbatim in the law, we have to explicit it for programming purposes. Concretely, we need a "metadata" section that defines the shape and types of the data used inside the law.
Let's start our metadata section by declaring the type information for the individual and the income tax computation:
@@Begin metadata@@
/*
declaration structure Individual:
data income content amount
declaration structure Article1:
data fixed_percentage content decimal
data income_tax content amount
*/
@@End metadata@@
Each of this declaration is a structure, containing one or more data fields. Structures are useful to group together data that goes together. Usually, you get one structure per concrete object on which the law applies (like the individual), but also one structure for each article that defines quantities (like the article 1). It is up to you to decide how to group the data together, but you should aim to optimize code readability.
Sometimes, the law gives an enumeration of different situations. These enumerations are modeled in Catala using an enumeration type, like:
@@Begin metadata@@
/*
declaration enumeration TaxCredit:
-- NoTaxCredit
-- ChildrenTaxCredit content integer # the integer corresponds
# to the number of children
*/
@@End metadata@@
We've defined and typed the data that the program will manipulate. Now we have to define the logical context in which these data will evolve. This is done in Catala using "scopes". Scopes also have to be declared in metadata, so here we go:
@@Begin metadata@@
/*
declaration scope IncomeTaxComputation:
context individual content Individual
context article1 content Article1
*/
@@End metadata@@
This scope declaration says that whenever we're in the scope "IncomeTaxComputation", then we have access to two elements in context, namely the individual's data and the data defined by article 1. We will be able to refer to the lowercase variables in our code, either to use them or to define them or one of their part.
We now have everything to annotate the contents of article 1, which is copied over below.
@Article 1@
The income tax for an individual is defined as a fixed percentage of the individual's income over a year.
/*
scope IncomeTaxComputation:
definition article1.income_tax equals
invidual.income * article1.fixed_percentage
*/
In the code, we are defining inside our scope the amount of the income tax according to the formula described in the article. When defining formulaes, you have access to all the usual arithmetic operators. But what is the value of that fixed percentage? Often, precise values are defined elsewhere in the legislative source. Here, let's suppose we have:
@Article 2@
The fixed percentage mentionned at article 1 is equal to 20 %.
/*
scope IncomeTaxComputation:
definition article1.fixed_percentage equals 20 %
*/
You can see here that Catala allows definitions to be scattered throughout the annotation of the legislative text, so that each
definition is as close as possible to its location in the text.
@@Conditional definitions@@
So far so good, but now the legislative text introduces some trickyness. Let us suppose the third article says:
@Article 3@ If the individual is in charge of 2 or more children, then the fixed percentage mentionned at article 1 is equal to 15 %.
/*
# How to redefine article1.fixed_percentage?
*/
This article actually gives another definition for the fixed percentage, which was already defined in article 2. However, article 3 defines the percentage conditionnally to the individual having more than 2 children. Catala allows you precisely to redefine a variable under a condition:
/*
scope IncomeTaxComputation:
definition article1.fixed_percentage under condition
individual.number_of_children >= 2
2020-05-18 10:47:13 +03:00
consequence equals 15 %
2020-05-17 19:51:00 +03:00
*/
When the Catala program will execute, the right definition will be dynamically chosen by looking at which condition is true. A correctly drafted legislative source should always ensure that at most one condition is true at all times. However, if it is not the case, Catala will let you define a precedence on the conditions, which has to be justified by the law.
2020-05-18 00:01:07 +03:00
@@Functions@@
2020-05-18 10:47:13 +03:00
Catala lets you define functions anywhere in your data. Here's what it looks like in the metadata definition when we want to define a two-brackets tax computation:
2020-05-18 00:01:07 +03:00
@@Begin metadata@@
/*
declaration structure TwoBrackets:
data breakpoint content amount
data rate1 content decimal
data rate2 content decimal
declaration scope TwoBracketsTaxComputation :
context brackets content TwoBrackets
context tax_formula content amount depends on amount
*/
@@End metadata@@
And in the code:
@Article4@ The tax amount for a two-brackets computation is equal to the amount of income in each bracket multiplied by the rate of each bracket.
/*
scope TwoBracketsTaxComputation :
definition tax of income equals
if income <= breakpoint then
income * rate1
else (
breakpoint * rate1 + (income - breakpoint) * rate2
)
*/
@@Scope inclusion@@
Now that we've defined our helper scope for computing a two-brackets tax, we want to use it in our main tax computation scope.
2020-05-18 10:47:13 +03:00
@Article 5@ For individuals whose income is greater than $100,000, the income tax of article 1 is computed with a two-brackets system.
2020-05-18 00:01:07 +03:00
/*
scope IncomeTaxComputation :
includes two_brackets_for_rich scope TwoBracketsTaxComputation
definition article1.income_tax under condition
individual.income >= $100,000
consequence equals
two_brackets_for_rich.tax of individual.income
*/
Scope inclusion also comes with a syntactic sugar for quickly and conditionnaly
connecting context quantities :
@@Begin metadata@@
/*
declaration scope ExemptedOfTax:
context article1 content Article1
*/
@@End metadata@@
@Article 6@
2020-05-18 10:47:13 +03:00
Individuals earning less than $10,000 are exempted of the income tax mentionned at article 1.
2020-05-18 00:01:07 +03:00
/*
scope ExemptedOfTax :
definition article1.income_tax equals $0
scope IncomeTaxComputation:
includes tax_exempt scope ExemptedOfTax context
article1 = article1
under condition
individual.income <= $10,000
*/
2020-05-18 10:47:13 +03:00
This snippet of code actually brings the definition of article1.income_tax of ExemptedOfTax into the IncomeTaxComputation scope, prefixing it with the "income under $10,000" condition.