mirror of
https://github.com/CatalaLang/catala.git
synced 2024-11-15 01:45:38 +03:00
237 lines
8.3 KiB
Plaintext
237 lines
8.3 KiB
Plaintext
@@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
|
|
consequence equals 15 %
|
|
*/
|
|
|
|
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.
|
|
|
|
|
|
@@Functions@@
|
|
|
|
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:
|
|
@@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.
|
|
|
|
@Article 5@ For individuals whose income is greater than $100,000, the income
|
|
tax of article 1 is computed with a two-brackets system.
|
|
/*
|
|
declaration scope IncomeTaxComputation:
|
|
# The scope inclusion has to be added in the scope declaration
|
|
context two_brackets_for_rich scope TwoBracketsTaxComputation
|
|
|
|
scope IncomeTaxComputation :
|
|
|
|
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@
|
|
Individuals earning less than $10,000 are exempted of the income tax mentionned
|
|
at article 1.
|
|
/*
|
|
scope ExemptedOfTax :
|
|
definition article1.income_tax equals $0
|
|
|
|
declaration scope IncomeTaxComputation:
|
|
# The scope inclusion has to be added in the scope declaration
|
|
context tax_exempt scope ExemptedOfTax
|
|
|
|
scope IncomeTaxComputation:
|
|
definition article1.income_tax under condition
|
|
individual.income <= $10,000
|
|
consequence equals
|
|
tax_exempt.article1.income_tax
|
|
*/
|
|
|
|
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.
|