Skip to content

docs: started work on a type reference#3590

Closed
wizard7377 wants to merge 3 commits into
idris-lang:mainfrom
wizard7377:typeDocs
Closed

docs: started work on a type reference#3590
wizard7377 wants to merge 3 commits into
idris-lang:mainfrom
wizard7377:typeDocs

Conversation

@wizard7377
Copy link
Copy Markdown

Description

Created a reference for types

Comment thread docs/source/reference/types.rst Outdated
Comment thread docs/source/reference/types.rst Outdated
Comment thread docs/source/reference/types.rst Outdated
Comment thread docs/source/reference/types.rst Outdated
Comment thread docs/source/reference/types.rst Outdated
Comment thread docs/source/reference/types.rst Outdated
Comment thread docs/source/reference/types.rst Outdated
@wizard7377
Copy link
Copy Markdown
Author

Made some preliminary changes

@wizard7377 wizard7377 force-pushed the typeDocs branch 2 times, most recently from 7539471 to 5ca2aeb Compare August 6, 2025 18:52
Comment thread docs/source/reference/types.rst Outdated
Comment thread docs/source/reference/types.rst Outdated
Auto implicits are most useful in proofs, where they differ from regular implicits by irrelevance.
That is, a regular default will never initiate *anything* that cannot otherwise be initiated, while an ``auto`` default will not change anything outside of the input that cannot be initiated.

For instance, if we want to automatically pass a proof through some functions, we use ``auto`` defaults.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
For instance, if we want to automatically pass a proof through some functions, we use ``auto`` defaults.
For instance, if we want to automatically pass a proof through some functions, we use ``auto`` implicits.

Comment thread docs/source/reference/types.rst Outdated
Comment thread docs/source/reference/types.rst Outdated
Comment thread docs/source/reference/types.rst Outdated
Comment thread docs/source/reference/types.rst Outdated
Comment thread docs/source/reference/types.rst Outdated
@wizard7377 wizard7377 force-pushed the typeDocs branch 2 times, most recently from 772ac00 to 7fe032b Compare August 7, 2025 20:25
@wizard7377 wizard7377 marked this pull request as ready for review August 7, 2025 21:42
Copy link
Copy Markdown
Collaborator

@andrevidela andrevidela left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I skipped the middle because I thought this would be quick but I spent way longer than I thought. There is enough to work with before tackling the middle anyways

Comment thread docs/source/reference/types.rst Outdated
Implicits
^^^^^^^^^^^^^

Implicit function types, those where the value of a parameter can be inferred from the context, can take three forms.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Implicit function types, those where the value of a parameter can be inferred from the context, can take three forms.
Implicit arguments, can take three forms.

Comment thread docs/source/reference/types.rst Outdated
Comment on lines +24 to +25
The first of these, ``{x : A} -> B``, forms the basis "basic" implicit types.
That is, ``x`` should be inferred *syntactically*.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The first of these, ``{x : A} -> B``, forms the basis "basic" implicit types.
That is, ``x`` should be inferred *syntactically*.
The first one, ``{x : a} -> b`` is the most basic form of implicit arguments, that is
``x`` should be inferred *syntactically*.

Comment thread docs/source/reference/types.rst Outdated
Implicit function types, those where the value of a parameter can be inferred from the context, can take three forms.
The first of these, ``{x : A} -> B``, forms the basis "basic" implicit types.
That is, ``x`` should be inferred *syntactically*.
This is the equivalent of implicit ``forall`` in Haskell or Rocq, where we might state that ``vectorMap`` on a vector might be:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add a footnote here pointing people toward the difference between polymorphism and dependent types. I don't think it belongs in this document as a paragraph but it should probably be mentionned somewhere

Comment thread docs/source/reference/types.rst Outdated

vectorMap {n = m} f v

These two examples show the power of Idris implicits: while they can be inferred by the compiler, if necessary (or desired) they may be specified by the user
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
These two examples show the power of Idris implicits: while they can be inferred by the compiler, if necessary (or desired) they may be specified by the user
These two examples show the power of Idris implicits: while they can be inferred by the compiler, if necessary (or desired) they may be specified by the user.

Comment thread docs/source/reference/types.rst Outdated
Comment on lines +46 to +47
Idris has *two* additional modifiers of implicits, however.
The first, while not that important to the type system of Idris, is *incredibly* useful, and it is the default implicit.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Idris has *two* additional modifiers of implicits, however.
The first, while not that important to the type system of Idris, is *incredibly* useful, and it is the default implicit.
The second form of implicits arguments is the default implicit.

Comment thread docs/source/reference/types.rst Outdated
The other way to define top level types, ``record``, is documented in detail on the `records`_ page.

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Existentials in Types
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Existentials in Types
Inferable Placeholders

I don't know what to call this class of terms but existential is extremely confusing because there is already something called existential types in programming and it's not what is exposed here. Existential types are usually an encoding of sigma-types for languages without dependent types.

Comment thread docs/source/reference/types.rst Outdated
Comment on lines +247 to +249
While not restricted to types, existentials are so prevalent within types that there usage bears mentioning.
Existentials are always of the form ``_``, ``?`` or ``?NAME``, where ``NAME`` is a valid name.
Named existentials are scoped by *module*, however, they may only exist in one term.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
While not restricted to types, existentials are so prevalent within types that there usage bears mentioning.
Existentials are always of the form ``_``, ``?`` or ``?NAME``, where ``NAME`` is a valid name.
Named existentials are scoped by *module*, however, they may only exist in one term.
There is a class of expression that allow to call directly into Idris's inference machine, they are ``_``, ``?`` and ``?identifier``, where ``identifier`` is a valid variable name.
``_`` tells the compiler to wait for this expression to be resolved by another constraint, this is like a normal implicit argument.
``?`` tells the compiler to try to guess what the value is, this is like an auto-implicit.
``?identifiers`` is a **hole**. It allows you to query the type of the value at that point in the program.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think ? is like an auto-implicit (you need %search for that). I'm pretty sure it's solved by inference. The difference between _ and ? is that ? can be solved later. If you use _ in a type signature it's an error if it is not solved at the end of a signature. If you use ?, it can be solved later in the file. (An error if not solved by the end of the file.)

Comment thread docs/source/reference/types.rst Outdated

.. caution::

Existentials are scoped over modules.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Existentials are scoped over modules.
Holes are scoped over modules.

Comment thread docs/source/reference/types.rst Outdated
These can occur in types, although typically occur in generated ones.
Most often, this will occur in usages of generic types, where, for instance, given ``show : {a : Type} -> Show a => a -> String``, we transform the context ``show : {a : Type} -> Show a => a -> String, y = show x |- y : String`` to ``x : ?a, Show ?a |- y : String`` [#f2]_ .

``?`` is similar except, while if ``?a``` cannot be inferred it is made it a typed hole, if ``?`` cannot be inferred, it raises an error
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
``?`` is similar except, while if ``?a``` cannot be inferred it is made it a typed hole, if ``?`` cannot be inferred, it raises an error

? is completely different as it infers a value in addition to the type. Holes only infer the type.

Comment thread docs/source/reference/types.rst Outdated
Comment on lines +256 to +264
Named existential forms an equivalent to "typed holes", that is, a value to be filled in later.
These can occur in types, although typically occur in generated ones.
Most often, this will occur in usages of generic types, where, for instance, given ``show : {a : Type} -> Show a => a -> String``, we transform the context ``show : {a : Type} -> Show a => a -> String, y = show x |- y : String`` to ``x : ?a, Show ?a |- y : String`` [#f2]_ .
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this needs to be reworked in light of the previous changes

Copy link
Copy Markdown
Collaborator

@andrevidela andrevidela left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay I've only gone through a little bit of this but looking a the overall document I wonder where in the documentation this would fit.

it's definitely not a reference document, it's more like an informal beginner tutorial.
It also repeats information that's already in the idris crash course but in a less structured way, that's not bad in itself but it makes it hard to categorise. It also seems to be aimed at beginners but also makes references to and assumes Haskell knowledge which is already a small niche and it already addressed by the crash course. Finally, it contains many more things than types such as interfaces, quantities and holees.

My suggestion is that this should be broken down into a smaller document that would sit in front of the crash course and would be something like "an idris overview in 5 minutes" and that would allow to talk about all the different topics with only surface-level detail.

Another option would be to keep the same audience, surface-level interest people with some FP experience, and expand it into an actual tutorial,but that's a lot more work so I do not suggest it

what do you think?

Comment on lines +16 to +17
In addition, to do simple universal quantification, one can write ``forall x . a``, where ``x`` must be only a name (it can't have a type qualifier).
This is desugared to ``{0 x : _} -> a``.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be moved to the next section, we haven't introduced implicits or quantities yet so there is no point in writing down what the desugaring is. Also there is no universal quantification in Idris although there is a forall keyword, calling it that might be misleading.I'll let you judge how to rephrase that,maybe there is another sentence that also uses the phrase "universal quantification" that isn't suggesting Idris has universal quantification

Holes are scoped over modules.

Named holes occur most often in the context of type inference.
Most often, this will occur in usages of generic types, where, for instance, given ``show : {a : Type} -> Show a => a -> String``, we transform the context ``show : {a : Type} -> Show a => a -> String, y = show x |- y : String`` to ``x : ?a, Show ?a |- y : String`` [#f2]_ .
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the example is very insightful if all the steps are skipped. It's also a lot to introduce new syntax 90% of the way through the document

Comment on lines +232 to +234
In addition, this means that one can have anonymous instances, so, for instance, ``Monad (\x => x)`` is a perfectly valid form.

Even so, it is in general not a good idea to create such instances
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
In addition, this means that one can have anonymous instances, so, for instance, ``Monad (\x => x)`` is a perfectly valid form.
Even so, it is in general not a good idea to create such instances

If it's not a good idea to do it, we should not encourage users to do it

The two main ways to declare types at the top level are ``record`` and ``data``

.. note::
Type synonyms, type families, and the like from Haskell are all just normal functions from ``Type`` to something else.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Type synonyms, type families, and the like from Haskell are all just normal functions from ``Type`` to something else.
Type synonyms, type families, and the like from Haskell are all just normal functions ``Type -> a``

Copy link
Copy Markdown
Contributor

@stefan-hoeck stefan-hoeck Aug 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, aren't these functions that result in a type? For instance, a type synonym is just

Label : Type
Label = String

Same for type families? In fact, we hardly ever write functions of the type Type -> a.

Copy link
Copy Markdown
Collaborator

@andrevidela andrevidela Aug 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type families both result in a type (kind) and depend on types given as argument, I've put a because you could be working with multiple kinds not just *. open type families is closest to pattern matching on types, data families are like an indexed interface a -> Type. None of those comparaisons actually make any sense if you think too hard about it. Maybe the paragraph should be scraped because there isn't much pedagogical benefit in relating dependent types to haskell-specific features that don't quite match

Comment on lines +242 to +243
To declare (Agda style) Generalized Algebraic Data Types, we must write ``data NAME : KIND where CONS``.
``KIND`` must be a kind (in Idris there isn't actually distinction between types and kinds) whose tail ultimately ends up returning the type ``Type``.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are no kinds in Idris those are types


Even so, it is in general not a good idea to create such instances

``data`` declares (General) Algebraic Data Types ((G)ADTs).
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
``data`` declares (General) Algebraic Data Types ((G)ADTs).
``data`` declares (Generalized) Algebraic Data Types ((G)ADTs).

a bit weird to call them that because there is no difference between normal data types and gadts in Idris. I would reformulate as "data can also declare types with indicies, that is, where the parameter is a value that can vary depending on the constructor used."

It's actually the other data that's a special compiler case and it desugars to a data type with constant indices

In addition, each ``ALT`` must be of the form ``CONS PARAMS`` where each ``CONS`` is either an operator or a name (that will be declared as a constructor).
Finally, each of ``PARAMS`` must be a valid type.

To declare (Agda style) Generalized Algebraic Data Types, we must write ``data NAME : KIND where CONS``.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Saying that adga has gadts is also weird to me. adga has indexed types and you can use them to write down parameterised data types. it's only haskell that works the other way around

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I know there are people (see Conor's recent mastodon post) get offended if you refer to an indexed inductive type as a GADT.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found the post, quite amusing for us. Not amusing for them

@wizard7377
Copy link
Copy Markdown
Author

Probably a quick start at the beginning of the tutorial. I don't think there's an equivalent of that yet and that does seem rather important, so I'll get to work shortening it and adding the rest of basic Idris

@wizard7377
Copy link
Copy Markdown
Author

Because of the substantial differences both in content and purpose of the above changes, I have moved the development of this to a new pull request at #3618

@wizard7377 wizard7377 closed this Aug 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants