on 239c8ca help sign in
Idris-dev/docs/tutorial/typesfuns.rst
1129 lines 36 kB history raw
1.. _sect-typefuns:
3*******************
4Types and Functions
5*******************
7Primitive Types
8===============
10Idris defines several primitive types: ``Int``, ``Integer`` and
11``Float`` for numeric operations, ``Char`` and ``String`` for text
12manipulation, and ``Ptr`` which represents foreign pointers. There are
13also several data types declared in the library, including ``Bool``,
14with values ``True`` and ``False``. We can declare some constants with
15these types. Enter the following into a file ``Prims.idr`` and load it
16into the Idris interactive environment by typing ``idris
17Prims.idr``:
19.. code-block:: idris
21 module Prims
23 x : Int
24 x = 42
26 foo : String
27 foo = "Sausage machine"
29 bar : Char
30 bar = 'Z'
32 quux : Bool
33 quux = False
35An Idris file consists of an optional module declaration (here
36``module Prims``) followed by an optional list of imports and a
37collection of declarations and definitions. In this example no imports
38have been specified. However Idris programs can consist of several
39modules and the definitions in each module each have their own
40namespace. This is discussed further in Section
41:ref:`sect-namespaces`). When writing Idris programs both the order in which
42definitions are given and indentation are significant. Functions and
43data types must be defined before use, incidently each definition must
44have a type declaration, for example see ``x : Int``, ``foo :
45String``, from the above listing. New declarations must begin at the
46same level of indentation as the preceding declaration.
47Alternatively, a semicolon ``;`` can be used to terminate declarations.
49A library module ``prelude`` is automatically imported by every
50Idris program, including facilities for IO, arithmetic, data
51structures and various common functions. The prelude defines several
52arithmetic and comparison operators, which we can use at the prompt.
53Evaluating things at the prompt gives an answer, and the type of the
54answer. For example:
56::
58 *prims> 6*6+6
59 42 : Int
60 *prims> x == 6*6+6
61 True : Bool
63All of the usual arithmetic and comparison operators are defined for
64the primitive types. They are overloaded using type classes, as we
65will discuss in Section :ref:`sect-classes` and can be extended to
66work on user defined types. Boolean expressions can be tested with the
67``if...then...else`` construct, for example:
69::
71 *prims> if x == 6 * 6 + 6 then "The answer!" else "Not the answer"
72 "The answer!" : String
74Data Types
75==========
77Data types are declared in a similar way and with similar syntax to
78Haskell. Natural numbers and lists, for example, can be declared as
79follows:
81.. code-block:: idris
83 data Nat = Z | S Nat -- Natural numbers
84 -- (zero and successor)
85 data List a = Nil | (::) a (List a) -- Polymorphic lists
87The above declarations are taken from the standard library. Unary
88natural numbers can be either zero (``Z``), or the successor of
89another natural number (``S k``). Lists can either be empty (``Nil``)
90or a value added to the front of another list (``x :: xs``). In the
91declaration for ``List``, we used an infix operator ``::``. New
92operators such as this can be added using a fixity declaration, as
93follows:
95::
97 infixr 10 ::
99Functions, data constructors and type constructors may all be given
100infix operators as names. They may be used in prefix form if enclosed
101in brackets, e.g. ``(::)``. Infix operators can use any of the
102symbols:
104::
106 :+-*\/=.?|&><!@$%^~#
108Some operators built from these symbols can't be user defined. These are
109``:``, ``=>``, ``->``, ``<-``, ``=``, ``?=``, ``|``, ``**``,
110``==>``, ``\\``, ``%``, ``~``, ``?``, and ``!``.
112Functions
113=========
115Functions are implemented by pattern matching, again using a similar
116syntax to Haskell. The main difference is that Idris requires type
117declarations for all functions, using a single colon ``:`` (rather
118than Haskell’s double colon ``::``). Some natural number arithmetic
119functions can be defined as follows, again taken from the standard
120library:
122.. code-block:: idris
124 -- Unary addition
125 plus : Nat -> Nat -> Nat
126 plus Z y = y
127 plus (S k) y = S (plus k y)
129 -- Unary multiplication
130 mult : Nat -> Nat -> Nat
131 mult Z y = Z
132 mult (S k) y = plus y (mult k y)
134The standard arithmetic operators ``+`` and ``*`` are also overloaded
135for use by ``Nat``, and are implemented using the above functions.
136Unlike Haskell, there is no restriction on whether types and function
137names must begin with a capital letter or not. Function names
138(``plus`` and ``mult`` above), data constructors (``Z``, ``S``,
139``Nil`` and ``::``) and type constructors (``Nat`` and ``List``) are
140all part of the same namespace. We can test these functions at the
141Idris prompt:
143::
145 Idris> plus (S (S Z)) (S (S Z))
146 4 : Nat
147 Idris> mult (S (S (S Z))) (plus (S (S Z)) (S (S Z)))
148 12 : Nat
150.. note::
152 Idris automatically desugars the ``Nat`` representation into a
153 more human readable format. The result of ``plus (S (S Z)) (S (S Z))``
154 is actually ``(S (S (S (S Z))))`` which is the Integer 4. This can be
155 checked at the Idris prompt:
157::
159 Idris> (S (S (S (S Z))))
160 4 : Nat
162Like arithmetic operations, integer literals are also overloaded using
163type classes, meaning that we can also test the functions as follows:
165::
167 Idris> plus 2 2
168 4 : Nat
169 Idris> mult 3 (plus 2 2)
170 12 : Nat
172You may wonder, by the way, why we have unary natural numbers when our
173computers have perfectly good integer arithmetic built in. The reason
174is primarily that unary numbers have a very convenient structure which
175is easy to reason about, and easy to relate to other data structures
176as we will see later. Nevertheless, we do not want this convenience to
177be at the expense of efficiency. Fortunately, Idris knows about
178the relationship between ``Nat`` (and similarly structured types) and
179numbers. This means it can optimise the representation, and functions
180such as ``plus`` and ``mult``.
182``where`` clauses
183-----------------
185Functions can also be defined *locally* using ``where`` clauses. For
186example, to define a function which reverses a list, we can use an
187auxiliary function which accumulates the new, reversed list, and which
188does not need to be visible globally:
190.. code-block:: idris
192 reverse : List a -> List a
193 reverse xs = revAcc [] xs where
194 revAcc : List a -> List a -> List a
195 revAcc acc [] = acc
196 revAcc acc (x :: xs) = revAcc (x :: acc) xs
198Indentation is significant — functions in the ``where`` block must be
199indented further than the outer function.
201.. note:: Scope
203 Any names which are visible in the outer scope are also visible in
204 the ``where`` clause (unless they have been redefined, such as ``xs``
205 here). A name which appears only in the type will be in scope in the
206 ``where`` clause if it is a *parameter* to one of the types, i.e. it
207 is fixed across the entire structure.
209As well as functions, ``where`` blocks can include local data
210declarations, such as the following where ``MyLT`` is not accessible
211outside the definition of ``foo``:
213.. code-block:: idris
215 foo : Int -> Int
216 foo x = case isLT of
217 Yes => x*2
218 No => x*4
219 where
220 data MyLT = Yes | No
222 isLT : MyLT
223 isLT = if x < 20 then Yes else No
225In general, functions defined in a ``where`` clause need a type
226declaration just like any top level function. However, the type
227declaration for a function ``f`` *can* be omitted if:
229- ``f`` appears in the right hand side of the top level definition
231- The type of ``f`` can be completely determined from its first application
234So, for example, the following definitions are legal:
236.. code-block:: idris
238 even : Nat -> Bool
239 even Z = True
240 even (S k) = odd k where
241 odd Z = False
242 odd (S k) = even k
244 test : List Nat
245 test = [c (S 1), c Z, d (S Z)]
246 where c x = 42 + x
247 d y = c (y + 1 + z y)
248 where z w = y + w
250Dependent Types
251===============
253First Class Types
254-----------------
256In Idris, types are a first class language construct, meaning that they
257can be computed and manipulated (and passed to functions) just like any
258other language construct. For example, we could write a function which
259computes a type:
261.. code-block:: idris
263 isSingleton : Bool -> Type
264 isSingleton True = Nat
265 isSingleton False = List Nat
267This function calculates the appropriate type from a ``Bool`` which flags
268whether the type should be a singleton or not. We can use this function
269to calculate a type anywhere that a type can be used. For example, it
270can be used to calculate a return type:
272.. code-block:: idris
274 mkSingle : (x : Bool) -> isSingleton x
275 mkSingle True = 0
276 mkSingle False = []
278Or it can be used to have varying input types. The following function
279calculates either the sum of a list of ``Nat``, or returns the given
280``Nat``, depending on whether the singleton flag is true:
282.. code-block:: idris
284 sum : (single : Bool) -> isSingleton single -> Nat
285 sum True x = x
286 sum False [] = 0
287 sum False (x :: xs) = x + sum False xs
289Vectors
290-------
292A standard example of a dependent data type is the type of “lists with
293length”, conventionally called vectors in the dependent type
294literature. They are available as part of the Idris library, by
295importing ``Data.Vect``, or we can declare them as follows:
297.. code-block:: idris
299 data Vect : Nat -> Type -> Type where
300 Nil : Vect Z a
301 (::) : a -> Vect k a -> Vect (S k) a
303Note that we have used the same constructor names as for ``List``.
304Ad-hoc name overloading such as this is accepted by Idris,
305provided that the names are declared in different namespaces (in
306practice, normally in different modules). Ambiguous constructor names
307can normally be resolved from context.
309This declares a family of types, and so the form of the declaration is
310rather different from the simple type declarations above. We
311explicitly state the type of the type constructor ``Vect`` — it takes
312a ``Nat`` and a type as an argument, where ``Type`` stands for the
313type of types. We say that ``Vect`` is *indexed* over ``Nat`` and
314*parameterised* by ``Type``. Each constructor targets a different part
315of the family of types. ``Nil`` can only be used to construct vectors
316with zero length, and ``::`` to construct vectors with non-zero
317length. In the type of ``::``, we state explicitly that an element of
318type ``a`` and a tail of type ``Vect k a`` (i.e., a vector of length
319``k``) combine to make a vector of length ``S k``.
321We can define functions on dependent types such as ``Vect`` in the same
322way as on simple types such as ``List`` and ``Nat`` above, by pattern
323matching. The type of a function over ``Vect`` will describe what
324happens to the lengths of the vectors involved. For example, ``++``,
325defined as follows, appends two ``Vect``:
327.. code-block:: idris
329 (++) : Vect n a -> Vect m a -> Vect (n + m) a
330 (++) Nil ys = ys
331 (++) (x :: xs) ys = x :: xs ++ ys
333The type of ``(++)`` states that the resulting vector’s length will be
334the sum of the input lengths. If we get the definition wrong in such a
335way that this does not hold, Idris will not accept the definition.
336For example:
338.. code-block:: idris
340 (++) : Vect n a -> Vect m a -> Vect (n + m) a
341 (++) Nil ys = ys
342 (++) (x :: xs) ys = x :: xs ++ xs -- BROKEN
344When run through the Idris type checker, this results in the
345following:
347::
349 $ idris vbroken.idr --check
350 vbroken.idr:9:23:When elaborating right hand side of Vect.++:
351 When elaborating an application of constructor Vect.:::
352 Type mismatch between
353 Vect (k + k) a (Type of xs ++ xs)
354 and
355 Vect (plus k m) a (Expected type)
357 Specifically:
358 Type mismatch between
359 plus k k
360 and
361 plus k m
364This error message suggests that there is a length mismatch between
365two vectors — we needed a vector of length ``k + m``, but provided a
366vector of length ``k + k``.
368The Finite Sets
369---------------
371Finite sets, as the name suggests, are sets with a finite number of
372elements. They are available as part of the Idris library, by
373importing ``Data.Fin``, or can be declared as follows:
375.. code-block:: idris
377 data Fin : Nat -> Type where
378 FZ : Fin (S k)
379 FS : Fin k -> Fin (S k)
381From the signature, we can see that this is a type constructor that takes a ``Nat``, and produces a type.
382So this is not a set in the sense of a collection that is a container of objects,
383rather it is the canonical set of unnamed elements, as in "the set of 5 elements," for example.
384Effectively, it is a type that captures integers that fall into the range of zero to ``(n - 1)`` where
385``n`` is the argument used to instantiate the ``Fin`` type.
386For example, ``Fin 5`` can be thought of as the type of integers between 0 and 4.
388Let us look at the constructors in greater detail.
390``FZ`` is the zeroth element of a finite set with ``S k`` elements;
391``FS n`` is the ``n+1``\ th element of a finite set with ``S k``
392elements. ``Fin`` is indexed by a ``Nat``, which represents the number
393of elements in the set. Since we can’t construct an element of an
394empty set, neither constructor targets ``Fin Z``.
396As mentioned above, a useful application of the ``Fin`` family is to represent bounded
397natural numbers. Since the first ``n`` natural numbers form a finite
398set of ``n`` elements, we can treat ``Fin n`` as the set of integers
399greater than or equal to zero and less than ``n``.
401For example, the following function which looks up an element in a
402``Vect``, by a bounded index given as a ``Fin n``, is defined in the
403prelude:
405.. code-block:: idris
407 index : Fin n -> Vect n a -> a
408 index FZ (x :: xs) = x
409 index (FS k) (x :: xs) = index k xs
411This function looks up a value at a given location in a vector. The
412location is bounded by the length of the vector (``n`` in each case),
413so there is no need for a run-time bounds check. The type checker
414guarantees that the location is no larger than the length of the
415vector, and of course no less than zero.
417Note also that there is no case for ``Nil`` here. This is because it
418is impossible. Since there is no element of ``Fin Z``, and the
419location is a ``Fin n``, then ``n`` can not be ``Z``. As a result,
420attempting to look up an element in an empty vector would give a
421compile time type error, since it would force ``n`` to be ``Z``.
423Implicit Arguments
424------------------
426Let us take a closer look at the type of ``index``:
428.. code-block:: idris
430 index : Fin n -> Vect n a -> a
432It takes two arguments, an element of the finite set of ``n`` elements,
433and a vector with ``n`` elements of type ``a``. But there are also two
434names, ``n`` and ``a``, which are not declared explicitly. These are
435*implicit* arguments to ``index``. We could also write the type of
436``index`` as:
438.. code-block:: idris
440 index : {a:Type} -> {n:Nat} -> Fin n -> Vect n a -> a
442Implicit arguments, given in braces ``{}`` in the type declaration,
443are not given in applications of ``index``; their values can be
444inferred from the types of the ``Fin n`` and ``Vect n a``
445arguments. Any name beginning with a lower case letter which appears
446as a parameter or index in a
447type declaration, but which is otherwise unbound, will be automatically
448bound as an implicit argument. Implicit arguments can still be given
449explicitly in applications, using ``{a=value}`` and ``{n=value}``, for
450example:
452.. code-block:: idris
454 index {a=Int} {n=2} FZ (2 :: 3 :: Nil)
456In fact, any argument, implicit or explicit, may be given a name. We
457could have declared the type of ``index`` as:
459.. code-block:: idris
461 index : (i:Fin n) -> (xs:Vect n a) -> a
463It is a matter of taste whether you want to do this — sometimes it can
464help document a function by making the purpose of an argument more
465clear.
467“``using``” notation
468--------------------
470Sometimes it is useful to provide types of implicit arguments,
471particularly where there is a dependency ordering, or where the
472implicit arguments themselves have dependencies. For example, we may
473wish to state the types of the implicit arguments in the following
474definition, which defines a predicate on vectors:
476.. code-block:: idris
478 data Elem : a -> Vect n a -> Type where
479 Here : {x:a} -> {xs:Vect n a} -> Elem x (x :: xs)
480 There : {x,y:a} -> {xs:Vect n a} -> Elem x xs -> Elem x (y :: xs)
482An instance of ``Elem x xs`` states that ``x`` is an element of
483``xs``. We can construct such a predicate if the required element is
484``Here``, at the head of the vector, or ``There``, in the tail of the
485vector. For example:
487.. code-block:: idris
489 testVec : Vect 4 Int
490 testVec = 3 :: 4 :: 5 :: 6 :: Nil
492 inVect : Elem 5 testVec
493 inVect = There (There Here)
495If the same implicit arguments are being used a lot, it can make a
496definition difficult to read. To avoid this problem, a ``using`` block
497gives the types and ordering of any implicit arguments which can
498appear within the block:
500.. code-block:: idris
502 using (x:a, y:a, xs:Vect n a)
503 data Elem : a -> Vect n a -> Type where
504 Here : Elem x (x :: xs)
505 There : Elem x xs -> Elem x (y :: xs)
507Note: Declaration Order and ``mutual`` blocks
508---------------------------------------------
510In general, functions and data types must be defined before use, since
511dependent types allow functions to appear as part of types, and their
512reduction behaviour to affect type checking. However, this restriction
513can be relaxed by using a ``mutual`` block, which allows data types
514and functions to be defined simultaneously:
516.. code-block:: idris
518 mutual
519 even : Nat -> Bool
520 even Z = True
521 even (S k) = odd k
523 odd : Nat -> Bool
524 odd Z = False
525 odd (S k) = even k
527In a ``mutual`` block, first all of the type declarations are added,
528then the function bodies. As a result, none of the function types can
529depend on the reduction behaviour of any of the functions in the
530block.
532I/O
533===
535Computer programs are of little use if they do not interact with the
536user or the system in some way. The difficulty in a pure language such
537as Idris — that is, a language where expressions do not have
538side-effects — is that I/O is inherently side-effecting. Therefore in
539Idris, such interactions are encapsulated in the type ``IO``:
541.. code-block:: idris
543 data IO a -- IO operation returning a value of type a
545We’ll leave the definition of ``IO`` abstract, but effectively it
546describes what the I/O operations to be executed are, rather than how
547to execute them. The resulting operations are executed externally, by
548the run-time system. We’ve already seen one IO program:
550.. code-block:: idris
552 main : IO ()
553 main = putStrLn "Hello world"
555The type of ``putStrLn`` explains that it takes a string, and returns
556an element of the unit type ``()`` via an I/O action. There is a
557variant ``putStr`` which outputs a string without a newline:
559.. code-block:: idris
561 putStrLn : String -> IO ()
562 putStr : String -> IO ()
564We can also read strings from user input:
566.. code-block:: idris
568 getLine : IO String
570A number of other I/O operations are defined in the prelude, for
571example for reading and writing files, including:
573.. code-block:: idris
575 data File -- abstract
576 data Mode = Read | Write | ReadWrite
578 openFile : String -> Mode -> IO File
579 closeFile : File -> IO ()
581 fread : File -> IO String
582 fwrite : File -> String -> IO ()
583 feof : File -> IO Bool
585 readFile : String -> IO String
587.. _sect-do:
589“``do``” notation
590=================
592I/O programs will typically need to sequence actions, feeding the
593output of one computation into the input of the next. ``IO`` is an
594abstract type, however, so we can’t access the result of a computation
595directly. Instead, we sequence operations with ``do`` notation:
597.. code-block:: idris
599 greet : IO ()
600 greet = do putStr "What is your name? "
601 name <- getLine
602 putStrLn ("Hello " ++ name)
604The syntax ``x <- iovalue`` executes the I/O operation ``iovalue``, of
605type ``IO a``, and puts the result, of type ``a`` into the variable
606``x``. In this case, ``getLine`` returns an ``IO String``, so ``name``
607has type ``String``. Indentation is significant — each statement in
608the do block must begin in the same column. The ``return`` operation
609allows us to inject a value directly into an IO operation:
611.. code-block:: idris
613 return : a -> IO a
615As we will see later, ``do`` notation is more general than this, and
616can be overloaded.
618.. _sect-lazy:
620Laziness
621========
623Normally, arguments to functions are evaluated before the function
624itself (that is, Idris uses *eager* evaluation). However, this is
625not always the best approach. Consider the following function:
627.. code-block:: idris
629 ifThenElse : Bool -> a -> a -> a;
630 ifThenElse True t e = t;
631 ifThenElse False t e = e;
633This function uses one of the ``t`` or ``e`` arguments, but not both
634(in fact, this is used to implement the ``if...then...else`` construct
635as we will see later. We would prefer if *only* the argument which was
636used was evaluated. To achieve this, Idris provides a ``Lazy``
637data type, which allows evaluation to be suspended:
639.. code-block:: idris
641 data Lazy : Type -> Type where
642 Delay : (val : a) -> Lazy a
644 Force : Lazy a -> a
646A value of type ``Lazy a`` is unevaluated until it is forced by
647``Force``. The Idris type checker knows about the ``Lazy`` type,
648and inserts conversions where necessary between ``Lazy a`` and ``a``,
649and vice versa. We can therefore write ``ifThenElse`` as follows,
650without any explicit use of ``Force`` or ``Delay``:
652.. code-block:: idris
654 ifThenElse : Bool -> Lazy a -> Lazy a -> a;
655 ifThenElse True t e = t;
656 ifThenElse False t e = e;
658Useful Data Types
659=================
661Idris includes a number of useful data types and library functions
662(see the ``libs/`` directory in the distribution). This chapter
663describes a few of these. The functions described here are imported
664automatically by every Idris program, as part of ``Prelude.idr``.
666``List`` and ``Vect``
667---------------------
669We have already seen the ``List`` and ``Vect`` data types:
671.. code-block:: idris
673 data List a = Nil | (::) a (List a)
675 data Vect : Nat -> Type -> Type where
676 Nil : Vect Z a
677 (::) : a -> Vect k a -> Vect (S k) a
679Note that the constructor names are the same for each — constructor
680names (in fact, names in general) can be overloaded, provided that
681they are declared in different namespaces (see Section
682:ref:`sect-namespaces`), and will typically be resolved according to
683their type. As syntactic sugar, any type with the constructor names
684``Nil`` and ``::`` can be written in list form. For example:
686- ``[]`` means ``Nil``
688- ``[1,2,3]`` means ``1 :: 2 :: 3 :: Nil``
690The library also defines a number of functions for manipulating these
691types. ``map`` is overloaded both for ``List`` and ``Vect`` and
692applies a function to every element of the list or vector.
694.. code-block:: idris
696 map : (a -> b) -> List a -> List b
697 map f [] = []
698 map f (x :: xs) = f x :: map f xs
700 map : (a -> b) -> Vect n a -> Vect n b
701 map f [] = []
702 map f (x :: xs) = f x :: map f xs
704For example, given the following vector of integers, and a function to
705double an integer:
707.. code-block:: idris
709 intVec : Vect 5 Int
710 intVec = [1, 2, 3, 4, 5]
712 double : Int -> Int
713 double x = x * 2
715the function ``map`` can be used as follows to double every element in
716the vector:
718::
720 *usefultypes> show (map double intVec)
721 "[2, 4, 6, 8, 10]" : String
723You’ll find these examples in ``usefultypes.idr`` in the ``examples/``
724directory. For more details of the functions available on ``List`` and
725``Vect``, look in the library files:
727- ``libs/prelude/Prelude/List.idr``
729- ``libs/base/Data/List.idr``
731- ``libs/base/Data/Vect.idr``
733- ``libs/base/Data/VectType.idr``
735Functions include filtering, appending, reversing, and so on. Also
736remember that Idris is still in development, so if you don’t see
737the function you need, please feel free to add it and submit a patch!
739Aside: Anonymous functions and operator sections
740------------------------------------------------
742There are actually neater ways to write the above expression. One way
743would be to use an anonymous function:
745::
747 *usefultypes> show (map (\x => x * 2) intVec)
748 "[2, 4, 6, 8, 10]" : String
750The notation ``\x => val`` constructs an anonymous function which takes
751one argument, ``x`` and returns the expression ``val``. Anonymous
752functions may take several arguments, separated by commas,
753e.g. ``\x, y, z => val``. Arguments may also be given explicit types,
754e.g. ``\x : Int => x * 2``, and can pattern match,
755e.g. ``\(x, y) => x + y``. We could also use an operator section:
757::
759 *usefultypes> show (map (* 2) intVec)
760 "[2, 4, 6, 8, 10]" : String
762``(*2)`` is shorthand for a function which multiplies a number
763by 2. It expands to ``\x => x * 2``. Similarly, ``(2*)`` would expand
764to ``\x => 2 * x``.
766Maybe
767-----
769``Maybe`` describes an optional value. Either there is a value of the
770given type, or there isn’t:
772.. code-block:: idris
774 data Maybe a = Just a | Nothing
776``Maybe`` is one way of giving a type to an operation that may
777fail. For example, looking something up in a ``List`` (rather than a
778vector) may result in an out of bounds error:
780.. code-block:: idris
782 list_lookup : Nat -> List a -> Maybe a
783 list_lookup _ Nil = Nothing
784 list_lookup Z (x :: xs) = Just x
785 list_lookup (S k) (x :: xs) = list_lookup k xs
787The ``maybe`` function is used to process values of type ``Maybe``,
788either by applying a function to the value, if there is one, or by
789providing a default value:
791.. code-block:: idris
793 maybe : Lazy b -> (a -> b) -> Maybe a -> b
795Note that the type of the first argument is ``Lazy b`` rather than
796simply ``b``. Since the default value might not be used, we mark it as
797``Lazy`` in case it is a large expression where evaluating it then
798discarding it would be wasteful.
800Tuples and Dependent Pairs
801--------------------------
803Values can be paired with the following built-in data type:
805.. code-block:: idris
807 data Pair a b = MkPair a b
809As syntactic sugar, we can write ``(a, b)`` which, according to
810context, means either ``Pair a b`` or ``MkPair a b``. Tuples can
811contain an arbitrary number of values, represented as nested pairs:
813.. code-block:: idris
815 fred : (String, Int)
816 fred = ("Fred", 42)
818 jim : (String, Int, String)
819 jim = ("Jim", 25, "Cambridge")
821Dependent Pairs
822---------------
824Dependent pairs allow the type of the second element of a pair to depend
825on the value of the first element. Traditionally, these are referred to
826as “sigma types”:
828.. code-block:: idris
830 data Sigma : (a : Type) -> (P : a -> Type) -> Type where
831 MkSigma : {P : a -> Type} -> (x : a) -> P x -> Sigma a P
833Again, there is syntactic sugar for this. ``(a : A ** P)`` is the type
834of a pair of A and P, where the name ``a`` can occur inside ``P``.
835``( a ** p )`` constructs a value of this type. For example, we can
836pair a number with a ``Vect`` of a particular length.
838.. code-block:: idris
840 vec : (n : Nat ** Vect n Int)
841 vec = (2 ** [3, 4])
843If you like, you can write it out the long way, the two are precisely
844equivalent.
846.. code-block:: idris
848 vec : Sigma Nat (\n => Vect n Int)
849 vec = MkSigma 2 [3, 4]
851The type checker could of course infer the value of the first element
852from the length of the vector. We can write an underscore ``_`` in
853place of values which we expect the type checker to fill in, so the
854above definition could also be written as:
856.. code-block:: idris
858 vec : (n : Nat ** Vect n Int)
859 vec = (_ ** [3, 4])
861We might also prefer to omit the type of the first element of the
862pair, since, again, it can be inferred:
864.. code-block:: idris
866 vec : (n ** Vect n Int)
867 vec = (_ ** [3, 4])
869One use for dependent pairs is to return values of dependent types
870where the index is not necessarily known in advance. For example, if
871we filter elements out of a ``Vect`` according to some predicate, we
872will not know in advance what the length of the resulting vector will
873be:
875.. code-block:: idris
877 filter : (a -> Bool) -> Vect n a -> (p ** Vect p a)
879If the ``Vect`` is empty, the result is easy:
881.. code-block:: idris
883 filter p Nil = (_ ** [])
885In the ``::`` case, we need to inspect the result of a recursive call
886to ``filter`` to extract the length and the vector from the result. To
887do this, we use ``with`` notation, which allows pattern matching on
888intermediate values:
890.. code-block:: idris
892 filter p (x :: xs) with (filter p xs)
893 | ( _ ** xs' ) = if (p x) then ( _ ** x :: xs' ) else ( _ ** xs' )
895We will see more on ``with`` notation later.
897.. _sect-more-expr:
899More Expressions
900================
902``let`` bindings
903----------------
905Intermediate values can be calculated using ``let`` bindings:
907.. code-block:: idris
909 data Person = MkPerson String Int
911 showPerson : Person -> String
912 showPerson p = let MkPerson name age = p in
913 name ++ " is " ++ show age ++ " years old"
915We can do simple pattern matching in ``let`` bindings too. For
916example, we can extract fields from a record as follows, as well as by
917pattern matching at the top level:
919.. code-block:: idris
921 data Person = MkPerson String Int
923 showPerson : Person -> String
924 showPerson p = let MkPerson name age = p in
925 name ++ " is " ++ show age ++ " years old"
927List comprehensions
928-------------------
930Idris provides *comprehension* notation as a convenient shorthand
931for building lists. The general form is:
933::
935 [ expression | qualifiers ]
937This generates the list of values produced by evaluating the
938``expression``, according to the conditions given by the comma
939separated ``qualifiers``. For example, we can build a list of
940Pythagorean triples as follows:
942.. code-block:: idris
944 pythag : Int -> List (Int, Int, Int)
945 pythag n = [ (x, y, z) | z <- [1..n], y <- [1..z], x <- [1..y],
946 x*x + y*y == z*z ]
948The ``[a..b]`` notation is another shorthand which builds a list of
949numbers between ``a`` and ``b``. Alternatively ``[a,b..c]`` builds a
950list of numbers between ``a`` and ``c`` with the increment specified
951by the difference between ``a`` and ``b``. This works for any numeric
952type, using the ``count`` function from the prelude.
954``case`` expressions
955--------------------
957Another way of inspecting intermediate values of *simple* types is to
958use a ``case`` expression. The following function, for example, splits
959a string into two at a given character:
961.. code-block:: idris
963 splitAt : Char -> String -> (String, String)
964 splitAt c x = case break (== c) x of
965 (x, y) => (x, strTail y)
967``break`` is a library function which breaks a string into a pair of
968strings at the point where the given function returns true. We then
969deconstruct the pair it returns, and remove the first character of the
970second string.
972A ``case`` expression can match several cases, for example, to inspect
973an intermediate value of type ``Maybe a``. Recall ``list_lookup``
974which looks up an index in a list, returning ``Nothing`` if the index
975is out of bounds. We can use this to write ``lookup_default``, which
976looks up an index and returns a default value if the index is out of
977bounds:
979.. code-block:: idris
981 lookup_default : Nat -> List a -> a -> a
982 lookup_default i xs def = case list_lookup i xs of
983 Nothing => def
984 Just x => x
986If the index is in bounds, we get the value at that index, otherwise
987we get a default value:
989::
991 *usefultypes> lookup_default 2 [3,4,5,6] (-1)
992 5 : Integer
993 *usefultypes> lookup_default 4 [3,4,5,6] (-1)
994 -1 : Integer
996**Restrictions:** The ``case`` construct is intended for simple
997analysis of intermediate expressions to avoid the need to write
998auxiliary functions, and is also used internally to implement pattern
999matching ``let`` and lambda bindings. It will *only* work if:
1001- Each branch *matches* a value of the same type, and *returns* a
1002 value of the same type.
1004- The type of the result is "known". i.e. the type of the expression
1005 can be determined *without* type checking the ``case``-expression
1006 itself.
1008Dependent Records
1009=================
1011*Records* are data types which collect several values (the record's
1012*fields*) together. Idris provides syntax for defining records and
1013*automatically generating field access and update functions*. For
1014example, we can represent a person's name and age in a record:
1016.. code-block:: idris
1018 record Person where
1019 constructor MkPerson
1020 firstName, middleName, lastName : String
1021 age : Int
1023 fred : Person
1024 fred = MkPerson "Fred" "Joe" "Bloggs" 30
1026Records can have *parameters*, which are listed between the record
1027name and the ``where`` keyword, and *fields*, which are in an indented
1028block following the `where` keyword (here, ``firstName``, ``middleName``,
1029``lastName``, and ``age``). You can declare multiple fields on a single
1030line, provided that they have the same type. The constructor name is
1031provided after the ``constructor`` keyword. The field names can be used to
1032access the field values:
1036 *record> firstName fred
1037 "Fred" : String
1038 *record> age fred
1039 30 : Int
1040 *record> :t firstName
1041 firstName : Person -> String
1043We can also use the field names to update a record (or, more
1044precisely, produce a copy of the record with the given fields
1045updated):
1047.. code-block:: bash
1049 *record> record { firstName = "Jim" } fred
1050 MkPerson "Jim" "Joe" "Bloggs" 30 : Person
1051 *record> record { firstName = "Jim", age = 20 } fred
1052 MkPerson "Jim" "Joe" "Bloggs" 20 : Person
1054The syntax ``record { field = val, ... }`` generates a function which
1055updates the given fields in a record.
1057Records, and fields within records, can have dependent types. Updates
1058are allowed to change the type of a field, provided that the result is
1059well-typed.
1061.. code-block:: idris
1063 record Class where
1064 constructor ClassInfo
1065 students : Vect n Person
1066 className : String
1068It is safe to update the ``students`` field to a vector of a different
1069length because it will not affect the type of the record:
1071.. code-block:: idris
1073 addStudent : Person -> Class -> Class
1074 addStudent p c = record { students = p :: students c } c
1078 *record> addStudent fred (ClassInfo [] "CS")
1079 ClassInfo [MkPerson "Fred" "Joe" "Bloggs" 30] "CS" : Class
1081Nested record update
1082--------------------
1084Idris also provides a convenient syntax for accessing and updating
1085nested records. For example, if a field is accessible with the
1086expression ``c (b (a x))``, it can be updated using the following
1087syntax:
1089.. code-block:: idris
1091 record { a->b->c = val } x
1093This returns a new record, with the field accessed by the path
1094``a->b->c`` set to ``x``. The syntax is first class, i.e. ``record {
1095a->b->c = val }`` itself has a function type. Symmetrically, the field
1096can also be accessed with the following syntax:
1098.. code-block:: idris
1100 record { a->b->c } x
1102Parameters and Fields
1103---------------------
1105Records can have *parameters*, which are not subject to field
1106updates. The parameters appear as arguments to the resulting type, and
1107are written following the record type name. For example, a pair type
1108could be defined as follows:
1110.. code-block:: idris
1112 record Prod a b where
1113 constructor Times
1114 fst : a
1115 snd : b
1117The parameters to a record type need not be types. For example, we can
1118restrict the size of classes using a ``Nat`` parameter to the
1119``Class`` record:
1121.. code-block:: idris
1123 record SizedClass (size : Nat) where
1124 constructor SizedClassInfo
1125 students : Vect size Person
1126 className : String
1128Note that it is no longer possible to write ``addStudent`` for this
1129type, as that would change the size of the class.