1\section{Types and Functions}
3\subsection{Primitive Types}
5\Idris{} defines several primitive types: \tTC{Int}, \tTC{Integer} and
6\tTC{Float} for numeric operations, \tTC{Char} and \tTC{String} for
7text manipulation, and \tTC{Ptr} which represents foreign pointers.
8There are also several data types declared in the library, including
9\tTC{Bool}, with values \tDC{True} and \tDC{False}.
10We can declare some constants with these types. Enter the following
11into a file \texttt{prims.idr} and load it into the \Idris{} interactive
12environment by typing \texttt{idris prims.idr}:
14\begin{SaveVerbatim}{constprims}
22foo = "Sausage machine"
34An \Idris{} file consists of an optional module declaration (here
35\texttt{module prims}) followed by an optional list of imports (none here,
36however \Idris{} programs can consist of several modules, and the definitions
37in each module each have their own namespace, as we will discuss in Section
38\ref{sect:namespaces}) and a
39collection of declarations and definitions. Each definition must have a type
40declaration (here, \texttt{x : Int}, \texttt{foo : String}, etc).
41Indentation is significant --- a new declaration begins at the same level
42of indentation as the preceding declaration. Alternatively, declarations
43may be terminated with a semicolon.
45A library module \texttt{prelude} is automatically imported by every \Idris{} program,
46including facilities for IO, arithmetic, data structures and various common
47functions. The prelude defines several arithmetic and comparison operators,
48which we can use at the prompt. Evaluating things at the prompt gives an
49answer, and the type of the answer. For example:
51\begin{SaveVerbatim}{promptprim}
62All of the usual arithmetic and comparison operators are defined for the primitive
63types. They are overloaded using type classes, as we will discuss in Section
64\ref{sec:classes} and can be extended to work on user defined types.
65Boolean expressions can be tested with the \texttt{if...then...else} construct:
67\begin{SaveVerbatim}{ifthenelse}
69*prims> if x == 6 * 6 + 6 then "The answer!" else "Not the answer"
75\subsection{Data Types}
77Data types are declared in a similar way to Haskell data types, with a similar
78syntax. Natural numbers and lists, for example, can be declared as follows:
80\begin{SaveVerbatim}{natlist}
82data Nat = O | S Nat -- Natural numbers
83 -- (zero and successor)
84data List a = Nil | (::) a (List a) -- Polymorphic lists
90The above declarations are taken from the standard library. Unary natural
91numbers can be either zero (\texttt{O} - that's a capital letter 'o', not the digit), or
92the successor of another natural number (\texttt{S k}).
93Lists can either be empty (\texttt{Nil})
94or a value added to the front of another list (\texttt{x :: xs}).
95In the declaration for \tTC{List}, we used an infix operator \tDC{::}. New operators
96such as this can be added using a fixity declaration, as follows:
98\begin{SaveVerbatim}{infixcons}
106Functions, data constructors and type constuctors may all be given infix
107operators as names. They may be used in prefix form if enclosed in brackets,
108e.g. (::). Infix operators can use any of the symbols:
110\begin{SaveVerbatim}{infixsyms}
117\begin{SaveVerbatim}{argh}
121\subsection{Functions}
123Functions are implemented by pattern matching, again using a similar syntax to
124Haskell. The main difference is that \Idris{} requires type declarations for all
125functions, using a single colon \texttt{:} (rather than
126Haskell's double colon \texttt{::}). Some natural number arithmetic functions can be
127defined as follows, again taken from the standard library:
129\begin{SaveVerbatim}{natfns}
132plus : Nat -> Nat -> Nat
134plus (S k) y = S (plus k y)
136-- Unary multiplication
137mult : Nat -> Nat -> Nat
139mult (S k) y = plus y (mult k y)
145The standard arithmetic operators \texttt{+} and \texttt{*} are also overloaded
146for use by \texttt{Nat}, and are implemented
147using the above functions. Unlike Haskell, there is no restriction on whether
148types and function names must begin with a capital letter or not. Function
149names (\tFN{plus} and \tFN{mult} above), data constructors (\tDC{O}, \tDC{S},
150\tDC{Nil} and \tDC{::}) and type constructors (\tTC{Nat} and \tTC{List}) are
151all part of the same namespace.
153We can test these functions at the Idris prompt:
155\begin{SaveVerbatim}{fntest}
157Idris> plus (S (S O)) (S (S O))
159Idris> mult (S (S (S O))) (plus (S (S O)) (S (S O)))
160S (S (S (S (S (S (S (S (S (S (S (S O))))))))))) : Nat
166Like arithmetic operations, integer literals are also overloaded using type classes,
167meaning that we can also test the functions as follows:
169\begin{SaveVerbatim}{fntest}
173Idris> mult 3 (plus 2 2)
174S (S (S (S (S (S (S (S (S (S (S (S O))))))))))) : Nat
180You may wonder, by the way, why we have unary natural numbers when our
181computers have perfectly good integer arithmetic built in. The reason is
182primarily that unary numbers have a very convenient structure which is easy to
183reason about, and easy to relate to other data structures as we will see later.
184Nevertheless, we do not want this convenience to be at the expense of
185efficiency. Fortunately, \Idris{} knows about the relationship between
186\tTC{Nat} (and similarly structured types) and numbers, so optimises the
187representation and functions such as \tFN{plus} and \tFN{mult}.
189\subsubsection*{\texttt{where} clauses}
191Functions can also be defined \emph{locally} using \texttt{where} clauses. For example,
192to define a function which reverses a list, we can use an auxiliary function which
193accumulates the new, reversed list, and which does not need to be visible globally:
195\begin{SaveVerbatim}{revwhere}
197rev : List a -> List a
198rev xs = revAcc [] xs where
199 revAcc : List a -> List a -> List a
201 revAcc acc (x :: xs) = revAcc (x :: acc) xs
207Indentation is significant --- functions in the \texttt{where} block must be indented
208further than the outer function.
211Any names which are visible in the outer scope are also visible in the \texttt{where}
212clause (unless they have been redefined, such as \texttt{xs} here).
213\emph{However}, names which appear in the type are \emph{not} in scope. In particular,
214in the above example, the \texttt{a} in the top level type and the \texttt{a} in the
215auxiliary definifion \texttt{revAcc} are \emph{not} the same. If this is the required
216behaviour, the \texttt{a} can be brought into scope as follows:
218\begin{SaveVerbatim}{revwhereb}
220rev : List a -> List a
221rev {a} xs = revAcc [] xs where
222 revAcc : List a -> List a -> List a
228\subsection{Dependent Types}
230\subsubsection{Vectors}
232A standard example of a dependent type is the type of ``lists with length'',
233conventionally called vectors in the dependent type literature. In \Idris{},
234we declare vectors as follows:
236\begin{SaveVerbatim}{vect}
238data Vect : Set -> Nat -> Set where
240 (::) : a -> Vect a k -> Vect a (S k)
246Note that we have used the same constructor names as for \tTC{List}. Ad-hoc
247name overloading such as this is accepted by \Idris{}, provided that the names
248are declared in different namespaces (in practice, normally in different modules).
249Ambiguous constructor names can normally be resolved from context.
251This declares a family of types, and so the form of the declaration is rather
252different from the simple type declarations above. We explicitly state the type
253of the type constructor \tTC{Vect} --- it takes a type and a \tTC{Nat} as an
254argument, where \tTC{Set} stands for the type of types. We say that \tTC{Vect}
255is \emph{parameterised} by a type, and \emph{indexed} over \tTC{Nat}. Each
256constructor targets a different part of the family of types. \tDC{Nil} can only
257be used to construct vectors with zero length, and \tDC{::} to constructor
258vectors with non-zero length. In the type of \tDC{::}, we state explicitly that an element
259of type \texttt{a} and a tail of type \texttt{Vect a k} (i.e., a vector of length \texttt{k})
260combine to make a vector of length \texttt{S k}.
262We can define functions on dependent types such as \tTC{Vect} in the same way
263as on simple types such as \tTC{List} and \tTC{Nat} above, by pattern matching.
264The type of a function over \tTC{Vect} will describe what happens to the
265lengths of the vectors involved. For example, \tFN{app}, defined in the
266library, appends two \tTC{Vect}s:
268\begin{SaveVerbatim}{vapp}
270app : Vect A n -> Vect A m -> Vect A (n + m)
272app (x :: xs) ys = x :: app xs ys
278The type of \tFN{app} states that the resulting vector's length will be the sum of
279the input lengths. If we get the definition wrong in such a way that this does
280not hold, \Idris{} will not accept the definition. For example:
282\begin{SaveVerbatim}{vapperr}
284app : Vect a n -> Vect a m -> Vect a (n + m)
286app (x :: xs) ys = x :: app xs xs -- BROKEN
291\begin{SaveVerbatim}{vapperrmsg}
293$ idris vbroken.idr --check
294vbroken.idr:3:Can't unify Vect a (S (plus k k)) with Vect a (S (plus k m))
297\begin{SaveVerbatim}{bleh}
303This error message suggests that there is a length mismatch between two vectors
304--- we needed a vector of length \texttt{(S (k + m))}, but provided a vector
305of length \texttt{(S (k + k))}.
306Note that the terms in the error message have been \emph{normalised}, so in
307particular \texttt{n + m} has been reduced to \texttt{plus n m}.
309\subsubsection{The Finite Sets}
311Finite sets, as the name suggests, are sets with a finite number of elements.
312They are declared as follows (again, in the prelude):
314\begin{SaveVerbatim}{findecl}
316data Fin : Nat -> Set where
318 fS : Fin k -> Fin (S k)
324\tDC{fO} is the zeroth element of a finite set with \texttt{S k} elements;
326\texttt{n+1}th element of a finite set with \texttt{S k} elements.
327\tTC{Fin} is indexed by a \tTC{Nat}, which
328represents the number of elements in the set. Obviously we can't construct an
329element of an empty set, so neither constructor targets \texttt{Fin O}.
331A useful application of the \tTC{Fin} family is to represent numbers with
332guaranteed bounds. For example, the following function which looks up an element in a \tTC{Vect}
333is defined in the prelude:
335\begin{SaveVerbatim}{vlookup}
337lookup : Fin n -> Vect a n -> a
338lookup fO (x :: xs) = x
339lookup (fS k) (x :: xs) = lookup k xs
345This function looks up a value at a given location in a vector. The location is
346bounded by the length of the vector (\texttt{n} in each case), so there is no
347need for a run-time bounds check. The type checker guarantees that the location
348is no larger than the length of the vector.
350Note also that there is no case for \texttt{Nil} here. This is because it is
351impossible. Since there is no element of \texttt{Fin O}, and the location is a
352\texttt{Fin n}, then \texttt{n} can not be \tDC{O}. As a result, attempting to
353look up an element in an empty vector would give a compile time type error,
354since it would force \texttt{n} to be \tDC{O}.
356\subsubsection{Implicit Arguments}
358Let us take a closer look at the type of \texttt{lookup}:
360\begin{SaveVerbatim}{vlookupty}
362lookup : Fin n -> Vect a n -> a
368It takes two arguments, an element of the finite set of \texttt{n} elements, and a vector
369with \texttt{n} elements of type \texttt{a}. But there are also two names,
370\texttt{n} and \texttt{a}, which are not declared explictly. These are \emph{implicit}
371arguments to \texttt{lookup}. We could also write the type of \texttt{lookup} as:
373\begin{SaveVerbatim}{vlookupimpty}
375lookup : {a:Set} -> {n:Nat} -> Fin n -> Vect a n -> a
378\useverb{vlookupimpty}
381Implicit arguments, given in braces \texttt{\{\}} in the type declaration, are not given in
382applications of \texttt{lookup}; their values can be inferred from the types of
383the \texttt{Fin n} and \texttt{Vect a n} arguments. Any name which appears as a parameter
384or index in a type declaration, but which is otherwise free, will be automatically
385bound as an implicit argument.
386Implicit arguments can still be given explicitly in applications, using
387{a=value} and {n=value}, for example:
389\begin{SaveVerbatim}{vlookupexp}
391lookup {a=Int} {n=2} fO (2 :: 3 :: Nil)
397In fact, any argument, implicit or explicit, may be given a name. We could have
398declared the type of \texttt{lookup} as:
400\begin{SaveVerbatim}{vlookupn}
402lookup : (i:Fin n) -> (xs:Vect a n) -> a
408It is a matter of taste whether you want to do this --- sometimes it can help
409document a function by making the purpose of an argument more clear.
411\subsubsection{``\texttt{using}'' notation}
413Sometimes it is necessary to provide types of implicit arguments where
414the type checker can not work them out itself. This can happen if there is a
415dependency ordering --- obviously, \texttt{a} and \texttt{n} must be given as arguments above
416before being used --- or if an implicit argument has a complex type. For example,
417we will need to state the types of the implicit arguments in the following
418definition, which defines a predicate on vectors:
420\begin{SaveVerbatim}{elem}
422data Elem : a -> Vect a n -> Set where
423 here : {x:a} -> {xs:Vect a n} -> Elem x (x :: xs)
424 there : {x,y:a} -> {xs:Vect a n} -> Elem x xs -> Elem x (y :: xs)
430An instance of \texttt{Elem x xs} states that \texttt{x} is an element of
431\texttt{xs}. We can construct
432such a predicate if the required element is \texttt{here}, at the head of the vector,
433or \texttt{there}, in the tail of the vector. For example:
435\begin{SaveVerbatim}{testelem}
438testVec = 3 :: 4 :: 5 :: 6 :: Nil
440inVect : Elem 5 testVec
441inVect = there (there here)
447If the same implicit arguments are being used a lot, it can make a definition
448difficult to read. To avoid this problem, a \texttt{using} block gives the types and
449ordering of any implicit arguments which can appear within the block:
451\begin{SaveVerbatim}{elemusing}
453using (x:a, y:a, xs:Vect a n)
454 data Elem : a -> Vect a n -> Set where
455 here : Elem x (x :: xs)
456 there : Elem x xs -> Elem x (y :: xs)
463Computer programs are of little use if they do not interact with the user or
464the system in some way. The difficulty in a pure language such as \Idris{} ---
465that is, a language where expressions do not have side-effects --- is that I/O
466is inherently side-effecting. Therefore in \Idris{}, such interactions are
467encapsulated in the type \texttt{IO}:
469\begin{SaveVerbatim}{ioty}
471data IO a -- IO operation returning a value of type a
477We'll leave the definition of \texttt{IO} abstract, but effectively it describes what
478the I/O operations to be executed are, rather than how to execute them. The
479resulting operations are executed externally,
480by the run-time system. We've already seen one IO
483\begin{SaveVerbatim}{main}
486main = putStrLn "Hello world"
492The type of \texttt{putStrLn} explains that it takes a string, and returns an
493element of the unit type () via an I/O action. There is a variant \texttt{putStr} which
494outputs a string without a newline:
496\begin{SaveVerbatim}{putstr}
498putStrLn : String -> IO ()
499putStr : String -> IO ()
503We can also read strings from user input:
505\begin{SaveVerbatim}{getline}
513A number of other I/O operations are defined in the prelude, for example for reading and
514writing files, including:
516\begin{SaveVerbatim}{fileops}
519data Mode = Read | Write | ReadWrite
521openFile : String -> Mode -> IO File
522closeFile : File -> IO ()
524fread : File -> IO String
525fwrite : File -> String -> IO ()
526feof : File -> IO Bool
528readFile : String -> IO String
533\subsection{``\texttt{do}'' notation}
537I/O programs will typically need to sequence actions, feeding the output of one
538computation into the input of the next. \texttt{IO} is an abstract type, however, so we
539can't access the result of a computation directly. Instead, we sequence
540operations with \texttt{do} notation:
542\begin{SaveVerbatim}{greet}
545greet = do putStr "What is your name? "
547 putStrLn ("Hello " ++ name)
553The syntax \texttt{x <- iovalue} executes the I/O operation iovalue, of type
555puts the result, of type \texttt{a} into the variable \texttt{x}.
556In this case, \texttt{getLine} returns an \texttt{IO String},
557so \texttt{name} has type \texttt{String}. Indentation is significant --- each
558statement in the do block must begin in the same column.
559The \texttt{return} operation allows us to inject a value directly into an IO
562\begin{SaveVerbatim}{return}
570As we will see later, \texttt{do} notation is more general than this, and can be
573\subsection{Useful Data Types}
575\Idris{} includes a number of useful data types and library functions (see the
576\texttt{lib/} directory in the distribution). This chapter describes a few of these. The
577functions described here are imported automatically by every \Idris{} program, as
578part of \texttt{prelude.idr}.
580\subsubsection{\texttt{List} and \texttt{Vect}}
582We have already seen the \texttt{List} and \texttt{Vect} data types:
584\begin{SaveVerbatim}{listvec}
586data List a = Nil | (::) a (List a)
588data Vect : Set -> Nat -> Set where
590 (::) : a -> Vect a k -> Vect a (S k)
596Note that the constructor names are the same for each --- constructor names (in
597fact, names in general) can be overloaded, provided that they are declared in
598different namespaces (see Section \ref{sect:namespaces}), and will typically be
599resolved according to their type. As syntactic sugar, any type with the constructor
600names \texttt{Nil} and \texttt{::} can be written in list form. For example:
603\item \texttt{[]} means \texttt{Nil}
604\item \texttt{[1,2,3]} means \texttt{Cons 1 (Cons 2 (Cons 3 Nil))}
608The library also defines a number of functions for manipulating these types.
609\texttt{map} is overloaded both for \texttt{List} and \texttt{Vect}
610and applies a function to every element of the list or vector.
612\begin{SaveVerbatim}{map}
614map : (a -> b) -> List a -> List b
616map f (x :: xs) = f x :: map f xs
618map : (a -> b) -> Vect a n -> Vect b n
620map f (x :: xs) = f x :: map f xs
626For example, to double every element in a vector of integers:
628\begin{SaveVerbatim}{dvect}
631intVec = [1, 2, 3, 4, 5]
640You'll find these examples in \texttt{usefultypes.idr} in the \texttt{examples/} directory:
642\begin{SaveVerbatim}{rundvect}
644*usefultypes> show (map double intVec)
645"[2, 4, 6, 8, 10]" : String
651For more details of the functions available on \texttt{List} and \texttt{Vect},
652look in the library, in \texttt{prelude/list.idr} and \texttt{prelude/vect.idr} respectively.
653Functions include filtering, appending, reversing, and so on. Also remember
654that \Idris{} is still in development, so if you don't see the function you
655need, please feel free to add it and submit a patch!
657\subsubsection*{Aside: Anonymous functions and operator sections}
659There are actually neater ways to write the above expression. One way would be
660to use an anonymous function:
662\begin{SaveVerbatim}{lam1}
664*usefultypes> show (map (\x => x * 2) intVec)
665"[2, 4, 6, 8, 10]" : String
671The notation \texttt{$\backslash$x => val} constructs an anonymous function
672which takes one argument, \texttt{x} and returns the expression \texttt{val}.
673Anonymous functions may take several arguments, separated by commas, e.g.
674\texttt{$\backslash$x, y, z => val}. Arguments may also be given explicit
675types, e.g. \texttt{$\backslash$x : Int => x * 2}, and can pattern match,
676e.g. \texttt{$\backslash$ (x, y) => x + y}.
677We could also use an operator section:
679\begin{SaveVerbatim}{sec1}
681*usefultypes> show (map (* 2) intVec)
682"[2, 4, 6, 8, 10]" : String
688\texttt{(*2)} is shorthand for a function which multiplies a number by 2. It expands to
689\texttt{$\backslash$x => x * 2}.
690Similarly, \texttt{(2*)} would expand to \texttt{$\backslash$x => 2 * x}.
694\texttt{Maybe} describes an optional value. Either there is a value of the given type,
697\begin{SaveVerbatim}{maybe}
699data Maybe a = Just a | Nothing
705\texttt{Maybe} is one way of giving a type to an operation that may fail. For example,
706looking something up in a \texttt{List} (rather than a vector) may result in an out of
709\begin{SaveVerbatim}{lookuplist}
711list_lookup : Nat -> List a -> Maybe a
712list_lookup _ Nil = Nothing
713list_lookup O (x :: xs) = Just x
714list_lookup (S k) (x :: xs) = list_lookup k xs
720The \texttt{maybe} function is used to process values of type \texttt{Maybe},
721either by applying a function to the value, if there is one, or by providing a default value:
723\begin{SaveVerbatim}{maybefn}
725maybe : Maybe a -> |(default:b) -> (a -> b) -> b
731The vertical bar $\mid$ before the default value is a laziness annotation. Normally
732expressions are evaluated before being passed to a function. This is typically
733the most efficient behaviour. However, in this case, the default value might
734not be used and if it is a large expression, evaluating it will be wasteful.
735The $\mid$ annotation tells the compiler not to evaluate the argument until it is
738\subsubsection{Tuples and Dependent Pairs}
740Values can be paired with the following built-in data type:
742\begin{SaveVerbatim}{mkpair}
744data Pair a b = MkPair a b
750As syntactic sugar, we can write \texttt{(a, b)} which, according to context,
751means either \texttt{Pair a b} or \texttt{MkPair a b}.
752Tuples can contain an arbitrary number of values, represented as nested pairs:
754\begin{SaveVerbatim}{tuple}
759jim : (String, Int, String)
760jim = ("Jim", 25, "Cambridge")
765\subsubsection*{Dependent Pairs}
767Dependent pairs allow the type of the second element of a pair to depend on
768the value of the first element:
770\begin{SaveVerbatim}{sigma}
772data Exists : (A : Set) -> (P : A -> Set) -> Set where
773 Ex_intro : {P : A -> Set} -> (a : A) -> P a -> Exists A P
779Again, there is syntactic sugar for this. \texttt{(a : A ** P)} is the type of a pair of
780A and P, where the name \texttt{a} can occur inside P. \texttt{( a ** p )}
781constructs a value of this type. For example, we can pair a number with a
782\texttt{Vect} of a particular length.
784\begin{SaveVerbatim}{dvec}
786vec : (n : Nat ** Vect Int n)
793The type checker could of course infer the value of the first element from the
794length of the vector. We can write an underscore \texttt{\_} in place of values which we
795expect the type checker to fill in, so the above definition could also be
798\begin{SaveVerbatim}{dvec1}
800vec : (n : Nat ** Vect Int n)
807We might also prefer to omit the type of the first element of the pair, since,
808again, it can be inferred:
810\begin{SaveVerbatim}{dvec2}
812vec : (n ** Vect Int n)
819One use for dependent pairs is to return values of dependent types where the
820index is not necessarily known in advance. For example, if we filter elements
821out of a \texttt{Vect} according to some predicate, we will not know in advance what the
822length of the resulting vector will be:
824\begin{SaveVerbatim}{vfilter}
826filter : (a -> Bool) -> Vect a n -> (p ** Vect a p)
832If the \texttt{Vect} is empty, the result is easy:
834\begin{SaveVerbatim}{vfilternil}
836vfilter p Nil = (_ , [])
842In the \texttt{::} case, we need to inspect the result of a recursive call to
844extract the length and the vector from the result. To do this, we use \texttt{with}
845notation. with allows pattern matching on intermediate values:
847\begin{SaveVerbatim}{vfiltercons}
849filter p (x :: xs) with (filter p xs)
850 | ( _ ** xs' ) = if (p x) then ( _ ** x :: xs' ) else ( _ ** xs' )
856We will see more on \texttt{with} notation later.
858\subsection{\texttt{so}}
860The \texttt{so} data type is a predicate on \texttt{Bool} which guarantees that the
863\begin{SaveVerbatim}{sotype}
872This is most useful for providing a static guarantee that a dynamic check has been made.
873For example, we might provide a safe interface to a function which draws a pixel
874on a graphical display as follows, where \texttt{so (inBounds x y)} guarantees that
875the point \texttt{(x,y)} is within the bounds of a 640x480 window:
877\begin{SaveVerbatim}{soexample}
879inBounds : Int -> Int -> Bool
880inBounds x y = x >= 0 && x < 640 && y >= 0 && y < 480
882drawPoint : (x : Int) -> (y : Int) -> so (inBounds x y) -> IO ()
883drawPoint x y oh = unsafeDrawPoint x y
888\subsection{More Expressions}
890\subsubsection*{\texttt{let} bindings}
892Intermediate values can be calculated using \texttt{let} bindings:
894\begin{SaveVerbatim}{letb}
896mirror : List a -> List a
897mirror xs = let xs' = rev xs in
904We can do simple pattern matching in \texttt{let} bindings too. For example, we can extract
905fields from a record as follows, as well as by pattern matching at the top level:
907\begin{SaveVerbatim}{letp}
909data Person = MkPerson String Int
911showPerson : Person -> String
912showPerson p = let MkPerson name age = p in
913 name ++ " is " ++ show age ++ " years old"
918\subsubsection*{List comprehensions}
922\Idris{} provides \emph{comprehension} notation as a convenient shorthand for
923building lists. The general form is:
925\begin{SaveVerbatim}{listcomp}
927[ expression | qualifiers ]
933This generates the list of values produced by evaluating the
934\texttt{expression}, according to the conditions given by the comma separated
935\texttt{qualifiers}. For example, we can build a list of Pythagorean triples as
938\begin{SaveVerbatim}{triples}
940pythag : Int -> List (Int, Int, Int)
941pythag n = [ (x, y, z) | z <- [1..n], y <- [1..z], x <- [1..y],
948The \texttt{[a..b]} notation is another shorthand which builds a list of
949numbers between \texttt{a} and \texttt{b}. Alternatively \texttt{[a,b..c]}
950builds a list of numbers between \texttt{a} and \texttt{c} with the increment
951specified by the difference between \texttt{a} and \texttt{c}. This works for
952any numeric type, using the \texttt{count} function from the prelude.
954\subsubsection*{\texttt{case} expressions}
956Another way of inspecting intermediate values of \emph{simple} types
957is to use a \texttt{case} expression.
958The following function, for example, splits a string into two at a given character:
960\begin{SaveVerbatim}{split}
962splitAt : Char -> String -> (String, String)
963splitAt c x = case break (== c) x of
964 (x, y) => (x, strTail y)
970\texttt{break} is a library function which breaks a string into a pair of strings
971at the point where the given function returns true. We then deconstruct the
972pair it returns, and remove the first character of the second string.
974A \texttt{case} expression can match several cases, for example, to inspect an
975intermediate value of type \texttt{Maybe a}. Recall \texttt{list\_lookup} which
976looks up an index in a list, returning \texttt{Nothing} if the index is out
977of bounds. We can use this to write \texttt{lookup\_default}, which
978looks up an index and returns a default value if the index is out of bounds:
980\begin{SaveVerbatim}{listlookup}
982lookup_default : Nat -> List a -> a -> a
983lookup_default i xs def = case list_lookup i xs of
991If the index is in bounds, we get the value at that index, otherwise we get
994\begin{SaveVerbatim}{deftest}
996*usefultypes> lookup_default 2 [3,4,5,6] (-1)
998*usefultypes> lookup_default 4 [3,4,5,6] (-1)
1005\textbf{Restrictions:} The \texttt{case} construct is intended for simple analysis
1006of intermediate expressions to avoid the need to write auxiliary functions, and is
1007also used internally to implement pattern matching \texttt{let} and lambda bindings.
1008It will \emph{only} work if:
1011\item Each branch \emph{matches} a value of the same type, and \emph{returns} a
1012value of the same type.
1013\item The type of the result is ``known''. i.e. the type of the expression can be
1014determined \emph{without} type checking the \texttt{case}-expression itself.
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list