-
Notifications
You must be signed in to change notification settings - Fork 0
Language Features
This page lists all of Idris' language features, with (eventually) brief notes as to what they do.
- Full-spectrum dependent types
- Strict evaluation (plus
Lazy : Type -> Typetype constructor for explicit laziness) - Lambda, Pi (forall), Let bindings
- Pattern matching definitions
- Export modifiers
public,abstract,private - Function options
partial,total -
whereclauses - "magic with"
- Implicit arguments (in top level types)
- "Bound" implicit arguments
{n : Nat} -> {a : Type} -> Vect n a - "Unbound" implicit arguments ---
Vect n ais equivalent to the above in a type,nandaare implicitly bound. This applies to names beginning with a lower case letter in an argument position.
- "Bound" implicit arguments
- 'Tactic' implicit arguments, which are solved by running a tactic script or giving a default argument, rather than by unification.
- Unit type
(), empty typeVoid - Tuples (desugaring to nested pairs)
- Dependent pair syntax
(x : T ** P x)(there exists anxof typeTsuch thatP x) - Inline
caseexpressions - Heterogeneous equality
-
donotation - Idiom brackets
- Type classes, suppoting default methods and dependencies between methods
-
rewriteprfinexpr - Metavariables
- Inline proof/tactic scripts
- Implicit coercion
-
codata- Also
Inf : Type -> Typetype constructor for mixed data/codata. In factcodatais implemented by putting recusive arguments underInf.
- Also
-
syntaxrules for defining pattern and term syntactic sugar- these are used in the standard library to define
if ... then ... elseexpressions and an Agda-style preorder reasoning syntax.
- these are used in the standard library to define
-
Uniqueness typing using the
UniqueTypeuniverse. -
Partial evaluation by
[static]argument annotations.
Names can be defined in separate namespaces, and disambiguated by type. An expression with Name expr will privilege the namespace Name in the expression expr. For example:
Idris> with List [[1,2],[3,4],[5,6]]
[[1, 2], [3, 4], [5, 6]] : List (List Integer)
Idris> with Vect [[1,2],[3,4],[5,6]]
[[1, 2], [3, 4], [5, 6]] : Vect 3 (Vect 2 Integer)
Idris> [[1,2],[3,4],[5,6]]
Can't disambiguate name: Prelude.List.::, Prelude.Stream.::, Prelude.Vect.::
(| option1, option2, option3, ... |) type checks each of the options in turn until one of them works. This can be used to give simple automated proofs, e.g. for trying some constructors of proofs:
syntax Trivial = (| oh, refl |)
All definitions are checked for coverage (i.e. all well-typed applications are handled) and either for termination (i.e. all well-typed applications will eventually produce an answer) or, if returning codata, for productivity (in practice, all recursive calls are constructor guarded).
Obviously, termination checking is undecidable. In practice, the termination checker looks for size change - every cycle of recursive calls must have a decreasing argument, such as a recursive argument of a strictly positive data type.
There are two built-in functions which can be used to give the totality checker a hint:
-
assert_total xasserts that the expressionxis terminating and covering, even if the totality checker cannot tell. This can be used for example ifxuses a function which does not cover all inputs, but the caller knows that the specific input is covered. -
assert_smaller p xasserts that the expressionxis structurally smaller than the patternp.
For example, the following function is not checked as total:
qsort : Ord a => List a -> List a
qsort [] = []
qsort (x :: xs) = qsort (filter (<= x) xs) ++ (x :: qsort (filter (>= x) xs)))
This is because the checker cannot tell that filter will always produce a value smaller than the pattern x :: xs for the recursive call to qsort. We can assert that this will always be true as follows:
total
qsort : Ord a => List a -> List a
qsort [] = []
qsort (x :: xs) = qsort (assert_smaller (x :: xs) (filter (<= x) xs)) ++
(x :: qsort (assert_smaller (x :: xs) (filter (>= x) xs))))
This syntax is defined in the module Syntax.PreorderReasoning in the base package. It provides a syntax for composing proofs of reflexive-transitive relations, using overloadable functions called step and qed. This module also defines step and qed functions allowing the syntax to be used for demonstrating equality. Here is an example:
import Syntax.PreorderReasoning
multThree : (a, b, c : Nat) -> a * b * c = c * a * b
multThree a b c =
(a * b * c) ={ sym (multAssociative a b c) }=
(a * (b * c)) ={ cong (multCommutative b c) }=
(a * (c * b)) ={ multAssociative a c b }=
(a * c * b) ={ cong {f = (*b)} (multCommutative a c) }=
(c * a * b) QEDNote that the parentheses are required -- only a simple expression can be on the left of ={ }= or QED. Also, when using preorder reasoning syntax to prove things about equality, remember that you can only relate the entire expression, not subexpressions. This might occasionally require the use of cong.
Finally, although equality is the most obvious application of preorder reasoning, it can be used for any reflexive-transitive relation. Something like step1 ={ just1 }= step2 ={ just2 }= end QED is translated to (step step1 just1 (step step2 just2 (qed end))), selecting the appropriate definitions of step and qed through the normal disambiguation process. The standard library, for example, also contains an implementation of preorder reasoning on isomorphisms.
ty <== name applies the function name in such a way that it has the type ty, by matching ty against the function's type. This can be used in proofs, for example:
plus_comm : (n : Nat) -> (m : Nat) -> (n + m = m + n)
-- Base case
(Z + m = m + Z) <== plus_comm =
rewrite ((m + Z = m) <== plusZeroRightNeutral) ==>
(Z + m = m) in refl
-- Step case
(S k + m = m + S k) <== plus_comm =
rewrite ((k + m = m + k) <== plus_comm) in
rewrite ((S (m + k) = m + S k) <== plusSuccRightSucc) in
refl
Including %reflection functions and quoteGoal x by fn in t, which applies fn to the expected type of the current expression, and puts the result in x which is in scope when elaborating t.
- Error message reflection
- Eliminators
- Label types
'name
%logging n%unifyLog
New Foreign Function Interface
Tool Support
Community
- Mini Projects, for those interested in contributing
- Libraries, available elsewhere
- Idris Developer Meetings
- Tutorial: Type Providers and Foreign Functions
- The Zen of Idris
- Profiling
Feature proposals ("dragon eggs")