mirror of
https://github.com/GaloisInc/cryptol.git
synced 2024-12-04 06:16:00 +03:00
Small fixes for crash-course chapter of Programming Cryptol
Changes include spelling, grammar, punctuation, typesetting, and code formatting. A few factual errors have been fixed, and some Cryptol REPL output has been updated as well.
This commit is contained in:
parent
1528fb524d
commit
4cc76e6c8b
@ -13,7 +13,7 @@ Cryptol. This chapter provides an introduction to Cryptol, just to
|
||||
get you started. The exposition is not meant to be comprehensive, but
|
||||
rather as an overview to give you a feel of the most important tools
|
||||
available. If a particular topic appears hard to approach, feel free
|
||||
to skim it over for future reference.
|
||||
to skim it over for future reference.
|
||||
|
||||
A full language reference is beyond the scope of this document at this
|
||||
time.
|
||||
@ -37,13 +37,13 @@ Cryptol provides four basic data types: bits, sequences, tuples, and
|
||||
records. Words (i.e., numbers) are a special case of sequences. Note
|
||||
that, aside from bits, all other Cryptol types can be nested as deep
|
||||
as you like. That is, we can have records of sequences containing
|
||||
tuples that comprise of other records, etc., giving us a rich
|
||||
tuples made up of other records, etc., giving us a rich
|
||||
type-system for precisely describing the shapes of data our programs
|
||||
manipulate.
|
||||
|
||||
While Cryptol is statically typed, it uses type inference to supply
|
||||
unspecified types. That is, the user does {\em not} have to write the
|
||||
types of all expressions, they will be automatically inferred by the
|
||||
types of all expressions; they will be automatically inferred by the
|
||||
type-inference engine. Of course, in certain contexts the user might
|
||||
choose to supply a type explicitly. The notation is simple: we simply
|
||||
put the expression, followed by {\tt :} and the type. For instance:
|
||||
@ -140,7 +140,7 @@ in a non-standard base.\footnote{Cryptol does not support the input of
|
||||
|
||||
\note{Decimal numbers pose a problem in a bit-precise language like
|
||||
Cryptol. Numbers represented in a base that is a power of two
|
||||
unambiguausly specify the number of bits required to store each
|
||||
unambiguously specify the number of bits required to store each
|
||||
digit. For example {\tt 0b101} takes three bits to store. A
|
||||
hexadecimal digit takes 4 bits to store, so {\tt 0xabc} needs 12
|
||||
bits. On the other hand, in decimal, the number of bits is
|
||||
@ -148,7 +148,7 @@ in a non-standard base.\footnote{Cryptol does not support the input of
|
||||
to represent. When given a choice, Cryptol assumes the
|
||||
\emph{smallest} number of bits required to represent a decimal
|
||||
number. This is why Cryptol often prints messages like {\tt Assuming
|
||||
a = 3}; the value emitted are the number of bits necessary to
|
||||
a = 3}; the value emitted is the number of bits necessary to
|
||||
faithfully represent the decimal value on the corresponding line.}
|
||||
|
||||
\todo[inline]{2.1: Make decision about
|
||||
@ -365,7 +365,7 @@ Here are the responses from Cryptol:
|
||||
[10, 7, 4, 1]
|
||||
[]
|
||||
\end{Verbatim}
|
||||
Note how {\tt [10, 11 .. 1]} and {\tt [10, 9 .. 20]} give us empty
|
||||
Note how \texttt{[10, 11 ..\ 1]} and \texttt{[10, 9 ..\ 20]} give us empty
|
||||
sequences, since the upper bound is smaller than the lower bound in
|
||||
the former, and larger in the latter.
|
||||
\end{Answer}
|
||||
@ -395,7 +395,7 @@ can certainly be defined using Cryptol comprehensions.
|
||||
\begin{Verbatim}
|
||||
[ (x, y) | x <- [1 .. 3], y <- [4, 5] ]
|
||||
[ x + y | x <- [1 .. 3], y <- [] ]
|
||||
[ (x + y, z) | x <- [1, 2], y <- [1], z <- [3, 4] ]
|
||||
[ (x + y, z) | x <- [1, 2], y <- [1], z <- [3, 4] ]
|
||||
\end{Verbatim}
|
||||
What is the number of elements in the resulting sequence, with respect
|
||||
to the sizes of components?
|
||||
@ -403,7 +403,7 @@ to the sizes of components?
|
||||
\note{Recall that, when you type the expressions above, you will get
|
||||
messages from Cryptol such as {\tt Assuming a = 2}. This is Cryptol
|
||||
letting you know it has decided to use 2 bits to represent, for
|
||||
example, the value {\tt 3} in {\tt [1 .. 3]}. This information may
|
||||
example, the value \texttt{3} in \texttt{[1 ..\ 3]}. This information may
|
||||
not seem to matter now but it can be very helpful later
|
||||
on.}
|
||||
\end{Exercise}
|
||||
@ -415,9 +415,9 @@ Here are the responses from Cryptol:
|
||||
[(2, 3) (2, 4) (3, 3) (3, 4)]
|
||||
\end{Verbatim}
|
||||
The size of the result will be the sizes of the components
|
||||
multiplied. For instance, in the first example, the generator {\tt x
|
||||
<- [1 .. 3]} assigns 3 values to {\tt x}, and the generator {\tt y
|
||||
<- [4, 5]} assigns 2 values to {\tt y}; and hence the result has
|
||||
multiplied. For instance, in the first example, the generator
|
||||
\texttt{x <- [1 ..\ 3]} assigns 3 values to \texttt{x}, and the generator
|
||||
\texttt{y <- [4, 5]} assigns 2 values to \texttt{y}; and hence the result has
|
||||
$2\times 3 = 6$ elements.
|
||||
\end{Answer}
|
||||
|
||||
@ -442,16 +442,16 @@ Here are the responses from Cryptol:
|
||||
[(2, 3)]
|
||||
\end{Verbatim}
|
||||
In this case, the size of the result will be the minimum of the
|
||||
component sizes. For the first example, the generator {\tt x <- [1
|
||||
.. 3]} assigns 3 values to {\tt x}, and the generator {\tt y <- [4,
|
||||
5]} assigns 2 values to {\tt y}; and hence the result has $\min(2,3)
|
||||
= 2$ elements.
|
||||
component sizes. For the first example, the generator
|
||||
\texttt{x <- [1 ..\ 3]} assigns 3 values to \texttt{x}, and the generator
|
||||
\texttt{y <- [4, 5]} assigns 2 values to \texttt{y}; and hence the result has
|
||||
$\min(2,3) = 2$ elements.
|
||||
\end{Answer}
|
||||
|
||||
\begin{tip}
|
||||
One can mix parallel and cartesian comprehensions, where each
|
||||
parallel arm can contain multiple cartesian
|
||||
generators, or vice-versa.\indComp\indCartesian\indParallel
|
||||
generators.\indComp\indCartesian\indParallel
|
||||
\end{tip}
|
||||
|
||||
\begin{tip}
|
||||
@ -510,11 +510,11 @@ makes sense to you.
|
||||
|
||||
For sequences, the two basic operations are appending\indAppend ({\tt
|
||||
\#}) and selecting\indIndex elements out ({\tt @}, {\tt @@}, {\tt
|
||||
!}, and {\tt !!}). Forward selection operator ({\tt @}), starts
|
||||
!}, and {\tt !!}). The forward selection operator (\texttt{@}) starts
|
||||
counting from the beginning, while the backward selection
|
||||
operator\indRIndex ({\tt !}) starts from the end. Indexing always
|
||||
starts at zero: That is {\tt xs @ 0} is the first element of {\tt xs},
|
||||
while {\tt xs ! 0} is the last. The permutation\indIndexs
|
||||
starts at zero: that is, {\tt xs @ 0} is the first element of {\tt xs},
|
||||
while \texttt{xs !\ 0} is the last. The permutation\indIndexs
|
||||
versions\indRIndexs ({\tt @@} and {\tt !!}, respectively) allow us to
|
||||
concisely select multiple elements: they allow us to extract elements
|
||||
in any order (which makes them very useful for permuting sequences).
|
||||
@ -581,7 +581,7 @@ Here are Cryptol's responses:
|
||||
\begin{Exercise}\label{ex:seq:8}
|
||||
The permutation operators ({\tt @@} and {\tt !!}) can be defined
|
||||
using sequence comprehensions. Write an expression that selects the
|
||||
even indexed elements out of the sequence {\tt [0 .. 10]} first
|
||||
even indexed elements out of the sequence \texttt{[0 ..\ 10]} first
|
||||
using {\tt @@}, and then using a sequence comprehension.
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:seq:8}
|
||||
@ -612,7 +612,7 @@ elements available as demanded by the program.
|
||||
\begin{Exercise}\label{ex:seq:9}
|
||||
Try the following infinite enumerations:
|
||||
\begin{Verbatim}
|
||||
[1:[32] ... ]
|
||||
[1:[32] ...]
|
||||
[1:[32], 3 ...]
|
||||
[1:[32] ...] @ 2000
|
||||
[1:[32], 3 ...] @@ [300, 500, 700]
|
||||
@ -644,7 +644,7 @@ Try the following infinite enumerations:
|
||||
\begin{Answer}\ansref{ex:seq:10}
|
||||
Here is a simple test case:
|
||||
\begin{Verbatim}
|
||||
Cryptol> ([1 ... ]:[inf][32])!3
|
||||
Cryptol> ([1 ...]:[inf][32])!3
|
||||
|
||||
[error] at <interactive>:1:1--1:21:
|
||||
Unsolved constraint:
|
||||
@ -784,26 +784,26 @@ the result:\indSignature
|
||||
%% cryptol 1 said: : {a b c} (fin c,c >= 4,a*b == 12) => [a][b][c]
|
||||
|
||||
A complex type signature like this one first defines a set of type
|
||||
variables {\tt \Verb|{a, b, c}|}, a set of constraints on those
|
||||
variables {\tt \Verb|(a >= 4, fin a, fin c, 12 == b * c)|}, a {\tt =>}
|
||||
and finally the shape description. In this case, Cryptol's {\tt
|
||||
[b][c][a]} is telling us that the result will be a sequence of {\tt
|
||||
b} things, each of which is a sequence of {\tt c} things, each of
|
||||
which is a word of size {\tt a}. The type constraints tell us that
|
||||
{\tt a} is at least 4, because the maximum element of the sequence is 12,
|
||||
and it takes at least 4 bits to represent the value 12. The
|
||||
constraints are that {\tt b * c == 12}, which means we should
|
||||
completely cover the entire input, and that the lengths {\tt a} and
|
||||
{\tt c} need to be finite. As you can see, {\tt split} is a very
|
||||
powerful function. The flexibility afforded by {\tt split} comes in
|
||||
very handy in Cryptol. We shall see one example of its usage later in
|
||||
variables \verb|{a, b, c}|, a set of constraints on those variables
|
||||
\verb|(fin b, fin c, b * a == 12, c >= 4)|, a \texttt{=>} and finally
|
||||
the shape description. In this case, Cryptol's \texttt{[a][b][c]} is
|
||||
telling us that the result will be a sequence of \texttt{a} things,
|
||||
each of which is a sequence of \texttt{b} things, each of which is a
|
||||
word of size \texttt{c}. The type constraints tell us that \texttt{c}
|
||||
is at least 4, because the maximum element of the sequence is 12, and
|
||||
it takes at least 4 bits to represent the value 12. The other constraints
|
||||
are that \texttt{b * a == 12}, which means we should completely cover
|
||||
the entire input, and that the lengths \texttt{a} and \texttt{c} need
|
||||
to be finite. As you can see, \texttt{split} is a very powerful
|
||||
function. The flexibility afforded by \texttt{split} comes in very
|
||||
handy in Cryptol. We shall see one example of its usage later in
|
||||
Section~\ref{sec:scytale}.
|
||||
|
||||
\begin{Exercise}\label{ex:split:0}
|
||||
With a sequence of length 12, as in the above example, there are
|
||||
precisely 6 ways of splitting it: 1--12, 2--6, 3--4, 4--3, 6--2, and
|
||||
12--1. We have seen the first three splits above. Write the
|
||||
expressions corresponding to the latter 3.\indSplit
|
||||
expressions corresponding to the latter three.\indSplit
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:split:0}
|
||||
Here they are:\indSplit
|
||||
@ -818,8 +818,8 @@ Here they are:\indSplit
|
||||
\end{Answer}
|
||||
|
||||
\begin{Exercise}\label{ex:split:1}
|
||||
What happens when you type {\tt split [1 .. 12] :
|
||||
[5][2][8]}?\indSplit
|
||||
What happens when you type
|
||||
\texttt{split [1 ..\ 12] :\ [5][2][8]}?\indSplit
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:split:1}
|
||||
Cryptol will issue a type error:\indSplit
|
||||
@ -836,8 +836,8 @@ result (5*2), but the input has 12.
|
||||
\end{Answer}
|
||||
|
||||
\begin{Exercise}\label{ex:split:2}
|
||||
Write a {\tt split} expression to turn the sequence {\tt [1 .. 120]
|
||||
: [120][8]} into a nested sequence with type {\tt [3][4][10][8]},
|
||||
Write a \texttt{split} expression to turn the sequence \texttt{[1 ..\ 120]
|
||||
:\ [120][8]} into a nested sequence with type {\tt [3][4][10][8]},
|
||||
keeping the elements in the same order.\indSplit \lhint{Use nested
|
||||
comprehensions.} \indComp
|
||||
\end{Exercise}
|
||||
@ -1012,7 +1012,7 @@ observe:\indTake\indDrop\indSplit\indGroup
|
||||
\end{Verbatim}
|
||||
\end{Exercise}
|
||||
\noindent Recall that the notation {\tt 12:[6]} means the constant 12
|
||||
with the type precisely 6-bits wide.
|
||||
with the type precisely 6 bits wide.
|
||||
\begin{Answer}\ansref{ex:words:4}
|
||||
Remember that Cryptol is big-endian\indEndianness and hence {\tt
|
||||
12:[6]} is precisely {\tt [False, False, True, True, False,
|
||||
@ -1075,9 +1075,9 @@ shift a word, say {\tt 12:[6]} by one to the right:
|
||||
(12:[6]) >> 1
|
||||
= [False, False, True, True, False, False] >> 1
|
||||
= [False, False, False, True, True, False]
|
||||
= 6
|
||||
= 6
|
||||
\end{Verbatim}
|
||||
That is shifting-right by one effectively divides the word by 2. This
|
||||
That is shifting right by one effectively divides the word by 2. This
|
||||
is due to Cryptol's ``big-endian'' representation of
|
||||
numbers\footnote{This is a significant change from Cryptol version 1,
|
||||
which interpreted the leftmost element of a sequence as the
|
||||
@ -1110,8 +1110,8 @@ Here are Cryptol's responses:
|
||||
comes up often in computer science, with no clear
|
||||
winner.\indEndianness Since Cryptol allows indexing from the beginning
|
||||
or the end of a (finite) sequence, you can access the 0th
|
||||
(least-significant) bit of a sequence $k$ with $k$!0, the 1st bit with
|
||||
$k$!1, and so on.\indIndex
|
||||
(least-significant) bit of a sequence \texttt{k} with \texttt{k!0}, the 1st bit with
|
||||
\texttt{k!1}, and so on.\indIndex
|
||||
|
||||
%=====================================================================
|
||||
\section{Characters and strings}
|
||||
@ -1165,7 +1165,7 @@ which can be thought of records without field names\footnote{In fact,
|
||||
with their names being their 0-indexed position in the tuple. So
|
||||
{\tt (1,2).1 == 2}.}. Like a tuple, the fields of a record can be of
|
||||
any type. We construct records by listing the fields inside
|
||||
curly-braces, separated by commas. We project fields out of a record
|
||||
curly braces, separated by commas. We project fields out of a record
|
||||
with the usual dot-notation. Note that the order of fields in a
|
||||
record is immaterial.\indTheRecordType\indTheTupleType
|
||||
|
||||
@ -1287,9 +1287,9 @@ The {\tt zero} function returns {\tt 0}, ignoring its argument.
|
||||
\sectionWithAnswers{Arithmetic}{sec:arithmetic}
|
||||
|
||||
Cryptol supports the usual binary arithmetic operators {\tt +}, {\tt
|
||||
-}, {\tt *}, {\tt \Verb|^^|} (exponentiate), {\tt /} (integer
|
||||
-}, {\tt *}, {\tt \Verb|^^|} (exponentiation), {\tt /} (integer
|
||||
division), {\tt \%} (integer modulus), along with \emph{ceiling}
|
||||
logarithm base 2 {\tt lg2} and binary {\tt min} and {\tt max}.
|
||||
base-2 logarithm {\tt lg2} and binary {\tt min} and {\tt max}.
|
||||
|
||||
The important thing to remember is that all arithmetic in Cryptol is
|
||||
modular,\indModular with respect to the underlying word size. As a
|
||||
@ -1303,8 +1303,8 @@ explicitly.\indOverflow\indUnderflow\indPlus\indMinus\indTimes\indDiv\indMod\ind
|
||||
What is the value of {\tt 1+1}? Surprised?
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:arith:1}
|
||||
Since {\tt 1} requires only 1-bit to represent, the result also has
|
||||
1-bits. In other words, the arithmetic is done modulo $2^1 =
|
||||
Since {\tt 1} requires only 1 bit to represent, the result also has
|
||||
1 bit. In other words, the arithmetic is done modulo $2^1 =
|
||||
2$. Therefore, {\tt 1+1 = 0}.
|
||||
\end{Answer}
|
||||
|
||||
@ -1312,28 +1312,28 @@ What is the value of {\tt 1+1}? Surprised?
|
||||
What is the value of {\tt 1+(1:[8])}? Why?
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:arith:2}
|
||||
Now we have 8-bits to work with, so the result is {\tt 2}. Since we
|
||||
have 8-bits to work with, overflow will not happen until we get a
|
||||
Now we have 8 bits to work with, so the result is {\tt 2}. Since we
|
||||
have 8 bits to work with, overflow will not happen until we get a
|
||||
sum that is at least 256.
|
||||
\end{Answer}
|
||||
|
||||
\begin{Exercise}\label{ex:arith:3}
|
||||
What is the value of {\tt 3 - 5}? How about {\tt (3 - 5) : [8]}?
|
||||
What is the value of \texttt{3 - 5}? How about \texttt{(3 - 5) :\ [8]}?
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:arith:3}
|
||||
Recall from Section~\ref{sec:words} that there are no negative
|
||||
numbers in Cryptol. The values {\tt 3} and {\tt 5} can be
|
||||
represented in 3 bits, so Cryptol uses 3-bits to represent the
|
||||
numbers in Cryptol. The values \texttt{3} and \texttt{5} can be
|
||||
represented in 3 bits, so Cryptol uses 3 bits to represent the
|
||||
result, so the arithmetic is done modulo $2^3=8$. Hence, the result
|
||||
is {\tt 6}. In the second expression, we have 8-bits to work with,
|
||||
so the modulus is $2^8 = 256$; so the subtraction results in {\tt
|
||||
254} (or {\tt 0xfe}).
|
||||
is \texttt{6}. In the second expression, we have 8 bits to work with,
|
||||
so the modulus is $2^8 = 256$; so the subtraction results in
|
||||
\texttt{254} (or \texttt{0xfe}).
|
||||
\end{Answer}
|
||||
|
||||
\note{Cryptol supports subtraction both as a binary operator, and as a
|
||||
unary operator. When used in a unary fashion (a.k.a., unary
|
||||
minus),\indUnaryMinus it simply means subtraction from {\tt 0}. For
|
||||
instance, {\tt -5} precisely means {\tt 0-5}, and is subject to the
|
||||
unary operator. When used in a unary fashion (a.k.a. unary
|
||||
minus),\indUnaryMinus it simply means subtraction from \texttt{0}.
|
||||
For instance, \texttt{-5} precisely means \texttt{0-5}, and is subject to the
|
||||
usual modular arithmetic rules.}\indModular\indMinus
|
||||
|
||||
\begin{Exercise}\label{ex:arith:4}
|
||||
@ -1408,8 +1408,8 @@ How about {\tt max 5 (-2:[8])}? Why?\indMin\indModular\indUnaryMinus
|
||||
\end{Answer}
|
||||
|
||||
\begin{Exercise}\label{ex:arith:7}
|
||||
Write an expression that computes the sum of two sequences {\tt [1
|
||||
.. 10]} and {\tt [10, 9 .. 1]}.\indPlus
|
||||
Write an expression that computes the sum of two sequences
|
||||
\texttt{[1..\ 10]} and \texttt{[10, 9 ..\ 1]}.\indPlus
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:arith:7}
|
||||
The idiomatic Cryptol way of summing two sequences is to use a
|
||||
@ -1448,7 +1448,7 @@ Exercise~\ref{sec:sequences}--\ref{ex:seq:9}, we wrote the infinite
|
||||
enumeration\indEnum\indInfSeq starting at {\tt 1} using an explicit
|
||||
type as follows:
|
||||
\begin{Verbatim}
|
||||
[(1:[32]) ... ]
|
||||
[(1:[32]) ...]
|
||||
\end{Verbatim}
|
||||
As expected, Cryptol evaluates this expression to:
|
||||
\begin{Verbatim}
|
||||
@ -1463,7 +1463,7 @@ simply, by using a smaller bit size for the constant {\tt 1}:
|
||||
\begin{Verbatim}
|
||||
Cryptol> [(1:[2])...]
|
||||
[1, 2, 3, 0, 1 ...
|
||||
Cryptol> take`{20} [(1:[2])... ]
|
||||
Cryptol> take`{20} [(1:[2])...]
|
||||
[1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0]
|
||||
\end{Verbatim}
|
||||
We still get an infinite sequence, but the numbers will repeat
|
||||
@ -1473,12 +1473,12 @@ Cryptol's modular arithmetic.\indModular
|
||||
There is one more case to look at. What happens if we completely leave
|
||||
out the signature?
|
||||
\begin{Verbatim}
|
||||
Cryptol> [1 ... ]
|
||||
Cryptol> [1 ...]
|
||||
[1, 0, 1, 0, 1, ...]
|
||||
\end{Verbatim}
|
||||
In this case, Cryptol figured out that the number {\tt 1} requires
|
||||
precisely 1-bits, and hence the arithmetic is done modulo $2^1 = 2$,
|
||||
giving us the sequence $1$-$0$-$1$-$0$ \ldots. In particular, an
|
||||
precisely 1 bit, and hence the arithmetic is done modulo $2^1 = 2$,
|
||||
giving us the sequence $1,0,1,0,\ldots$ In particular, an
|
||||
enumeration of the form:
|
||||
\begin{Verbatim}
|
||||
[k ...]
|
||||
@ -1488,18 +1488,18 @@ will be treated as if the user has written:
|
||||
[k, (k+1) ...]
|
||||
\end{Verbatim}
|
||||
and type inference will assign the smallest bit-size possible to
|
||||
represent {\tt k}. \note{if the user evaluates the value of {\tt
|
||||
represent {\tt k}. \note{If the user evaluates the value of {\tt
|
||||
k+1}, then the result may be different. For example, {\tt [1, 1+1
|
||||
...]} results in the {\tt [ 1, 0, 1 ...]} behavior, but {\tt [1, 2
|
||||
...]} results in the {\tt [1, 0, 1 ...]} behavior, but {\tt [1, 2
|
||||
...]} adds another bit, resulting in {\tt [1, 2, 3, 0, 1, 2, 3
|
||||
...]}. If Cryptol evaluates the value of {\tt k+1}, the answer is
|
||||
modulo {\tt k}, so another bit is not added. For the curious, this
|
||||
subtle behavior was introduced to allow the sequence of all zeros to
|
||||
be written {\tt [0 ... ]}.}
|
||||
be written \texttt{[0 ...]}.}
|
||||
|
||||
\begin{Exercise}\label{ex:arith:9}
|
||||
Remember from Exercise~\ref{sec:words2}--\ref{ex:words:2} that the
|
||||
constant {\tt 0} requires 0-bits to represent. Based on this, what
|
||||
constant {\tt 0} requires 0 bits to represent. Based on this, what
|
||||
is the value of the enumeration {\tt [0..]}? What about {\tt
|
||||
[0...]}? Surprised?
|
||||
\end{Exercise}
|
||||
@ -1509,31 +1509,31 @@ Here are Cryptol's responses:\indModular\indEnum\indInfSeq
|
||||
[0]
|
||||
[0, 0, 0, 0, 0, ...]
|
||||
\end{Verbatim}
|
||||
as opposed to {\tt [0, 1, 0, 1, 0 ..]}, as one might
|
||||
as opposed to \texttt{[0, 1, 0, 1, 0, ...]}, as one might
|
||||
expect\footnote{This is one of the subtle changes from Cryptol 1. The
|
||||
previous behavior can be achieved by dropping the first element from
|
||||
{\tt [1 ... ]}.}. This behavior follows from the specification that
|
||||
\texttt{[1 ...]}.}. This behavior follows from the specification that
|
||||
the width of the elements of the sequence are derived from the width of
|
||||
the elements in the seed, which in this case is 0.
|
||||
\end{Answer}
|
||||
|
||||
\begin{Exercise}\label{ex:arith:10}
|
||||
What is the value of {\tt [1 .. 10]}? Explain in terms of the above
|
||||
What is the value of \texttt{[1 ..\ 10]}? Explain in terms of the above
|
||||
discussion on modular arithmetic.\indModular
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:arith:10}
|
||||
The expression {\tt [1 .. 10]} is equivalent to {\tt [1, (1+1)
|
||||
.. 10]}, and Cryptol knows that {\tt 10} requires at least 4-bits
|
||||
The expression \texttt{[1 ..\ 10]} is equivalent to \texttt{[1, (1+1) ..\ 10]},
|
||||
and Cryptol knows that \texttt{10} requires at least 4 bits
|
||||
to represent and uses the minimum implied by all the available
|
||||
information. Hence we get: {\tt [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}.
|
||||
You can use the {\tt :t} command to see the type Cryptol infers for
|
||||
information. Hence we get: \texttt{[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}.
|
||||
You can use the \texttt{:t} command to see the type Cryptol infers for
|
||||
this expression explicitly:
|
||||
\begin{Verbatim}
|
||||
Cryptol> :t [1 .. 10]
|
||||
{a} (a >= 4, fin a) => [10][a]
|
||||
\end{Verbatim}
|
||||
Cryptol tells us that the sequence has precisely $10$ elements, and each
|
||||
element is at least $4$-bits wide.
|
||||
element is at least $4$ bits wide.
|
||||
\todo[inline]{Reflect upon this ``at least'' a bit more.}
|
||||
\end{Answer}
|
||||
|
||||
@ -1551,7 +1551,7 @@ types can be used to specify the exact width of values, or shapes of
|
||||
sequences using a rich yet concise notation. In some cases, it may
|
||||
make sense to omit a type signature and let Cryptol {\em infer} the
|
||||
type for you. At the interpreter, you can check what type Cryptol
|
||||
inferred with the {\tt :t} command.
|
||||
inferred with the \texttt{:t} command.
|
||||
|
||||
\todo[inline]{More structured discussion of top and bottom types, \texttt{inf}
|
||||
and \texttt{fin}, and the precise kinds of type constraints that are
|
||||
@ -1562,14 +1562,14 @@ inferred with the {\tt :t} command.
|
||||
\label{sec:monomorphic-types}
|
||||
|
||||
A monomorphic type is one that represents a concrete value. Most of
|
||||
the examples we have seen so far falls into this category. Below, we
|
||||
the examples we have seen so far fall into this category. Below, we
|
||||
review the basic Cryptol types that make up all the monomorphic values
|
||||
in Cryptol.
|
||||
|
||||
\paragraph*{Bits}\indTheBitType\indTrue\indFalse There are precisely
|
||||
two bit values in Cryptol: {\tt True} and {\tt
|
||||
False}. The type itself is written {\tt Bit}. When we want to be
|
||||
explicit, we can write it as follows: {\tt (2 >= 3) : Bit}. However,
|
||||
explicit, we can write it as follows: \texttt{(2 >= 3) :\ Bit}. However,
|
||||
with type inference\indTypeInference writing the {\tt Bit} type
|
||||
explicitly is almost never needed.
|
||||
|
||||
@ -1591,22 +1591,22 @@ type {\tt [17]} is {\tt [17]Bit}, which we would say in English as
|
||||
collection of arbitrary number of
|
||||
elements. Just like we write a tuple value by enclosing it in
|
||||
parentheses, we write the tuple type by enclosing the component types
|
||||
in parentheses, separated by commas: {\tt (3, 5, True) : ([8], [32],
|
||||
Bit)}. Tuples' types follow the same structure: {\tt (2, (False, 3),
|
||||
5) : ([8], (Bit, [32]), [32])}. A tuple component can be any type:
|
||||
in parentheses, separated by commas: \texttt{(3, 5, True) :\ ([8], [32],
|
||||
Bit)}. Tuples' types follow the same structure: \texttt{(2, (False, 3),
|
||||
5) :\ ([8], (Bit, [32]), [32])}. A tuple component can be any type:
|
||||
a word, another tuple, sequence, record, etc. Again, type inference
|
||||
makes writing tuple types hardly ever necessary.\indTypeInference
|
||||
|
||||
\paragraph*{Sequences}\indTheSequenceType A sequence is simply a
|
||||
collection of homogeneous elements. If the element type is {\tt t},
|
||||
then we write the type of a sequence of {\tt n} elements as: {\tt
|
||||
[n]t}. Note that {\tt t} itself can be a sequence itself. For
|
||||
instance, the type: {\tt [12][3][6]} reads as follows: A sequence of
|
||||
\paragraph*{Sequences}\indTheSequenceType A sequence is simply a
|
||||
collection of homogeneous elements. If the element type is $t$,
|
||||
then we write the type of a sequence of $n$ elements as \texttt{[}$n$\texttt{]}$t$.
|
||||
Note that $t$ can be a sequence type itself. For
|
||||
instance, the type {\tt [12][3][6]} reads as follows: A sequence of
|
||||
12 elements, each of which is a sequence of 3 elements, each of which
|
||||
is a 6-bit wide word.
|
||||
is a 6-bit-wide word.
|
||||
|
||||
The type of an infinite sequence is written {\tt [inf]t}, where {\tt
|
||||
t} is the type of the elements.\indInfSeq \indInf
|
||||
The type of an infinite sequence is written \texttt{[inf]}$t$, where $t$
|
||||
is the type of the elements.\indInfSeq \indInf
|
||||
|
||||
\begin{Exercise}\label{ex:types:1}
|
||||
What is the total number of bits in the type {\tt [12][3][6]}?
|
||||
@ -1619,7 +1619,7 @@ What is the total number of bits in the type {\tt [12][3][6]}?
|
||||
|
||||
\begin{Exercise}\label{ex:types:2}
|
||||
How would you write the type of an infinite sequence where each
|
||||
element itself is an infinite sequence of 32 bit words? What is the
|
||||
element itself is an infinite sequence of 32-bit words? What is the
|
||||
total bit size of this type?
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:types:2} {\tt [inf][inf][32]}. The size of
|
||||
@ -1630,8 +1630,8 @@ What is the total number of bits in the type {\tt [12][3][6]}?
|
||||
A record is a heterogeneous collection of arbitrary number of labeled
|
||||
elements. In a sense, they generalize tuples by allowing the
|
||||
programmer to give explicit names to fields. The type of a record is
|
||||
written by enclosing it in braces, separated by commas: {\tt \{x :
|
||||
[32], y : [32]\}}. Records can be nested and can contain arbitrary
|
||||
written by enclosing it in braces, separated by commas:
|
||||
\texttt{\{x :\ [32], y :\ [32]\}}. Records can be nested and can contain arbitrary
|
||||
types of elements (records, sequences, functions, etc.).
|
||||
|
||||
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@ -1658,7 +1658,7 @@ element from a sequence, returning the remainder:
|
||||
Cryptol> tail [(False, (1:[8])), (True, 12), (False, 3)]
|
||||
[(True, 12), (False, 3)]
|
||||
Cryptol> tail [ (1:[16])... ]
|
||||
[2, 3, 4, 5, 6, ...
|
||||
[2, 3, 4, 5, 6, ...]
|
||||
\end{Verbatim}
|
||||
What exactly is the type of {\tt tail}? If we look at the first
|
||||
example, one can deduce that {\tt tail} must have the type:
|
||||
@ -1678,12 +1678,12 @@ must have the following types, respectively:
|
||||
tail : [inf][16] -> [inf][16]
|
||||
\end{Verbatim}
|
||||
|
||||
As we have emphasized before, Cryptol is strongly-typed, meaning that
|
||||
As we have emphasized before, Cryptol is strongly typed, meaning that
|
||||
every entity (whether a Cryptol primitive or a user-defined function)
|
||||
must have a well-defined type. Clearly, the types we provided for {\tt
|
||||
tail} above are quite different from each other. In particular, the
|
||||
must have a well-defined type. Clearly, the types we provided for
|
||||
\texttt{tail} above are quite different from each other. In particular, the
|
||||
first example uses numbers as the element type, while the second has
|
||||
tuples. So, how can {\tt tail} be assigned a type that will make it
|
||||
tuples. So, how can \texttt{tail} be assigned a type that will make it
|
||||
work on all these inputs?
|
||||
|
||||
If you are familiar C++ templates or Java generics, you might think
|
||||
@ -1705,9 +1705,9 @@ This is quite a different type from what we have seen so far. In
|
||||
particular, it is a polymorphic type, one that can work over multiple
|
||||
concrete instantiations of it. Here's how we read this type in
|
||||
Cryptol:
|
||||
\begin{quote} {\em tail} is a polymorphic function, parameterized over
|
||||
\begin{quote} \texttt{tail} is a polymorphic function, parameterized over
|
||||
{\tt a} and {\tt b}. The input is a sequence that contains {\tt a+1}
|
||||
elements. The elements can be of an arbitrary type {\tt b}, there
|
||||
elements. The elements can be of an arbitrary type {\tt b}; there
|
||||
is no restriction on their structure. The result is a sequence that
|
||||
contains {\tt a} elements, where the elements themselves has the
|
||||
same type as those of the input. \end{quote} In the case for {\tt
|
||||
@ -1724,7 +1724,7 @@ our running examples:
|
||||
offended or disappointed.}
|
||||
|
||||
\begin{center}
|
||||
\begin{adjustbox}{width={\textwidth},keepaspectratio}
|
||||
%\begin{adjustbox}{width={\textwidth},keepaspectratio}
|
||||
\begin{tabular}[h]{c||c|c|l}
|
||||
{\tt [a+1]b -> [a]b} & {\tt a} & {\tt b} & Notes \\ \hline\hline
|
||||
{\tt [5][8] -> [4][8]} & 4 & {\tt [8]} & {\tt a+1 = 5} $\Rightarrow$ {\tt a = 4} \\\hline
|
||||
@ -1732,7 +1732,7 @@ our running examples:
|
||||
{\tt [3](Bit, [8]) -> [2](Bit, [8])} & 2 & {\tt (Bit, [8])} & The type {\tt b} is now a tuple \\\hline
|
||||
{\tt [inf][16] -> [inf][16]} & {\tt inf} & {\tt [16]} & {\tt a+1 = inf} $\Rightarrow$ {\tt a = inf}
|
||||
\end{tabular}
|
||||
\end{adjustbox}
|
||||
%\end{adjustbox}
|
||||
\end{center}
|
||||
|
||||
In the last instantiation, Cryptol knows that $\infty - 1 = \infty$,
|
||||
@ -1751,7 +1751,7 @@ instantiation can not be found:
|
||||
Cryptol is telling us that it cannot match the types {\tt Bit} and the
|
||||
sequence {\tt [a+1]b}, causing a type error statically at compile
|
||||
time. (The funny notation of {\tt ?a} and {\tt ?b} are due to how type
|
||||
instantiations proceed under-the-hood. While they look funny at first,
|
||||
instantiations proceed under the hood. While they look funny at first,
|
||||
you soon get used to the notation.)
|
||||
|
||||
We should emphasize that Cryptol polymorphism\indPolymorphism
|
||||
@ -1775,8 +1775,8 @@ Is there any way to make the last example work by giving a type signature?
|
||||
Here is the type of {\tt groupBy}:
|
||||
\begin{Verbatim}
|
||||
Cryptol> :t groupBy
|
||||
groupBy : {each, parts, elem}
|
||||
(fin each) => [parts * each]elem
|
||||
groupBy : {each, parts, elem}
|
||||
(fin each) => [parts * each]elem
|
||||
-> [parts][each]elem
|
||||
\end{Verbatim}
|
||||
At every use case of {\tt groupBy} we must instantiate the parameters
|
||||
@ -1784,7 +1784,7 @@ At every use case of {\tt groupBy} we must instantiate the parameters
|
||||
instantiation will match the use case. In the first example, we can
|
||||
simply take: {\tt each = 3}, {\tt parts = 3}, and {\tt elem = [4]}. In
|
||||
the second, we can take {\tt each=3}, {\tt parts=4}, and {\tt
|
||||
elem=[4]}. The third expression does not type check. Cryptol tells
|
||||
elem=[4]}. The third expression does not type-check. Cryptol tells
|
||||
us:
|
||||
\begin{Verbatim}
|
||||
Cryptol> groupBy`{3} [1..10] : [3][2][8]
|
||||
@ -1816,7 +1816,7 @@ sizes.\indPredicates To illustrate the notion, consider the type of
|
||||
the Cryptol primitive {\tt take}\indTake:
|
||||
\begin{Verbatim}
|
||||
Cryptol> :t take
|
||||
take : {front, back, elem} (fin front) => [front + back]elem
|
||||
take : {front, back, elem} (fin front) => [front + back]elem
|
||||
-> [front]elem
|
||||
\end{Verbatim}
|
||||
|
||||
@ -1837,7 +1837,7 @@ Cryptol is telling us that it is unable to satisfy this instantiation
|
||||
(since {\tt front} is 10 and the sequence has 5
|
||||
elements).\indTake\indPredicates
|
||||
|
||||
In general, type predicates exclusively describe \texttt{arithmetic
|
||||
In general, type predicates exclusively describe \textit{arithmetic
|
||||
constraints on type variables}. Cryptol does not have a
|
||||
general-purpose dependent type system, but a \emph{size-polymorphic
|
||||
type system}. Often type variables' values are of finite size,
|
||||
@ -1862,7 +1862,7 @@ Here is another way, more direct but somewhat less satisfying:
|
||||
\begin{verbatim}
|
||||
{k} ((k - 128) * (k - 192) * (k - 256) == 0) => [k]
|
||||
\end{verbatim}
|
||||
Note that Cryptol's type constraints do not include {\em or} predicates,
|
||||
Note that Cryptol's type constraints do not include {\em or} predicates,
|
||||
hence we cannot just list the possibilities in a list.
|
||||
\end{Answer}
|
||||
|
||||
@ -1899,7 +1899,7 @@ these algorithms.
|
||||
%% Cryptol> :t 42
|
||||
%% 42 : [6]
|
||||
%%\end{Verbatim}
|
||||
%% However, {\tt 42} can in fact be of any size that is at least 6-bits
|
||||
%% However, {\tt 42} can in fact be of any size that is at least 6 bits
|
||||
%% wide. So, why does Cryptol think it is just 6 bits? The reason is
|
||||
%% because of defaulting.\indDefaulting The defaulting rule says that
|
||||
%% Cryptol will pick the minimum size that will satisfy the
|
||||
@ -1948,13 +1948,13 @@ these algorithms.
|
||||
|
||||
There is a spectrum of type systems employed by programming languages,
|
||||
all the way from completely untyped to fancier dependently typed
|
||||
languages. There is no simple answer to the question what type system
|
||||
languages. There is no simple answer to the question, what type system
|
||||
is the best? It depends on the application domain. We have found that
|
||||
Cryptol's size-polymorphic type system is a good fit for programming
|
||||
problems that arise in the domain of cryptography. The bit-precise
|
||||
type system makes sure that we never pass an argument that is 32-bits
|
||||
type system makes sure that we never pass an argument that is 32 bits
|
||||
wide in a buffer that can only fit 16. The motto is: {\em Well typed
|
||||
programs do not go wrong}.
|
||||
programs do not go wrong}.
|
||||
|
||||
In practical terms, this means that the type system catches most of
|
||||
the common mistakes that programmers tend to make. Size-polymorphism
|
||||
@ -1972,7 +1972,7 @@ the type system will reject some programs that makes perfect
|
||||
sense. But what is more important is that the type system will reject
|
||||
programs that will indeed go wrong at run-time. And the price you pay
|
||||
to make sure your program type-checks is negligible, and the savings
|
||||
due to type-checking can be enormous.
|
||||
due to type checking can be enormous.
|
||||
|
||||
The crucial question is not whether we want type systems, but rather
|
||||
what type system is the best for a given particular application
|
||||
@ -1991,7 +1991,7 @@ it gave us answers. This is great for experimenting, and exploring
|
||||
Cryptol itself. The next fundamental Cryptol idiom is the notion of a
|
||||
function. You have already used built-in functions {\tt +}, {\tt
|
||||
take}, etc.\indPlus\indLg Of course, users can define their own
|
||||
functions as well. Currently the Cryptol interpeter does not support
|
||||
functions as well. Currently the Cryptol interpreter does not support
|
||||
defining functions, so you must define them in a file and load it, as
|
||||
in the next exercises.
|
||||
|
||||
@ -2016,7 +2016,7 @@ In particular, try the following invocations:
|
||||
increment 255
|
||||
increment 912
|
||||
\end{Verbatim}
|
||||
Do you expect the last call to type check?
|
||||
Do you expect the last call to type-check?
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:fn:0}
|
||||
Here are some example uses of {\tt increment}:
|
||||
@ -2035,15 +2035,15 @@ Note how type inference rejects application when applied to an
|
||||
argument of the wrong size: 912 is too big to fit into 8 bits.
|
||||
\end{Answer}
|
||||
|
||||
\note{Note that we do not have to parenthesize the argument to {\tt
|
||||
\note{We do not have to parenthesize the argument to {\tt
|
||||
increment}, as in {\tt increment(3)}. Function application is
|
||||
simply juxtaposition in Cryptol. However, you can put the
|
||||
simply juxtaposition in Cryptol. However, you can write the
|
||||
parentheses if you want to, and you must use parentheses if you want
|
||||
to pass a negative argument (e.g., {\tt increment(-2)} (recall
|
||||
\autoref{ex:arith:5})}\indFunApp
|
||||
to pass a negative argument, e.g. \texttt{increment(-2)} (recall
|
||||
Exercise~\autoref{ex:arith:5}).}\indFunApp
|
||||
|
||||
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
\subsection{Local names: {\ttfamily{\textbf where}}-clauses}
|
||||
\subsection{Local names: {\ttfamily{\textbf where}} clauses}
|
||||
\label{sec:local-names:-ttfam}
|
||||
|
||||
You can create local bindings in a {\tt where} clause\indWhere, to
|
||||
@ -2077,15 +2077,16 @@ What is the signature of the function telling us?
|
||||
\begin{Answer}\ansref{ex:fn:1.1}
|
||||
Here is the type Cryptol infers:
|
||||
\begin{verbatim}
|
||||
Cryptol> :t twoPlusXY
|
||||
Cryptol> :t twoPlusXY
|
||||
twoPlusXY : {a} (a >= 2, fin a) => ([a],[a]) -> [a]
|
||||
\end{verbatim}
|
||||
That is, our function will actually work over arbitrary (finite) sized
|
||||
words, as long as they are at least 2-bits wide. The 2-bit requirement
|
||||
words, as long as they are at least 2 bits wide. The 2-bit requirement
|
||||
comes from the constant 2, which requires at least 2 bits to
|
||||
represent.
|
||||
\end{Answer}
|
||||
|
||||
\todo[inline]{The Cmp class has not been introduced yet. At least, add a forward reference to the ``Type classes'' section.}
|
||||
\begin{Exercise}\label{ex:fn:2}
|
||||
Define a function with the following signature:
|
||||
\begin{Verbatim}
|
||||
@ -2160,12 +2161,12 @@ for obvious reasons, and hence the {\tt fin n} constraint.
|
||||
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
\subsection{\texorpdfstring{\lamexs}{Lambda-expressions}}\label{sec:lamex}
|
||||
|
||||
One particular use case of a {\tt where}-clause\indWhere is to
|
||||
One particular use case of a {\tt where} clause\indWhere is to
|
||||
introduce a helper function. If the function is simple enough, though,
|
||||
it may not be worth giving it a name. A \lamex fits the bill in these
|
||||
cases, where you can introduce an unnamed function as an
|
||||
expression. The syntax differs from ordinary definitions in two minor
|
||||
details: instead of the name we use the backslash or ``wack''
|
||||
details: instead of the name we use the backslash or ``whack''
|
||||
character, `{\tt \Verb|\|}', and the equals sign is replaced by an
|
||||
arrow `{\tt ->}'. (Since these functions do not have explicit names,
|
||||
they are sometimes referred to as ``anonymous functions'' as well. We
|
||||
@ -2219,10 +2220,10 @@ sequence {\tt xs} yield {\tt True} for the function {\tt f}.
|
||||
Cryptol> all eqTen [10, 10, 10, 5] where eqTen x = x == 10
|
||||
False
|
||||
\end{Verbatim}
|
||||
(The {\tt where}-clause introduces a local definition that is in scope
|
||||
in the current expression. We will see the details in
|
||||
(The {\tt where} clause introduces a local definition that is in scope
|
||||
in the current expression. We have seen the details in
|
||||
Section~\ref{sec:funcs}.\indWhere) What is the value of {\tt all f []}
|
||||
for any {\tt f}? Is this reasonable?
|
||||
for an arbitrary function {\tt f}? Is this reasonable?
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:zero:1}
|
||||
\begin{code}
|
||||
@ -2635,7 +2636,7 @@ In this diagram the stream is seeded with four initial values ({\tt
|
||||
3F, E2, 65, CA}). The subsequent elements ({\tt new}) are appended
|
||||
to the stream, and are computed by xor-ing the current stream element
|
||||
with two additional elements extracted from further into the stream.
|
||||
The output from the stream is a sequence of values, known as 'a's.
|
||||
The output from the stream is a sequence of values, known as $a$s.
|
||||
|
||||
The Cryptol code corresponding to this stream equation is:
|
||||
\begin{code}
|
||||
@ -2647,7 +2648,7 @@ The Cryptol code corresponding to this stream equation is:
|
||||
\end{code}
|
||||
|
||||
% \vfill
|
||||
% \eject
|
||||
% \eject
|
||||
\todo[inline]{Make sure pagination looks good, particularly for figures.}
|
||||
|
||||
\begin{Exercise}\label{ex:streamEq}
|
||||
@ -2693,7 +2694,7 @@ be used for readability and documentation. Type synonyms allow users
|
||||
to give names to arbitrary types. In this sense, they are akin to
|
||||
{\tt typedef} declarations in C~\cite{TheCProgrammingLanguage}.
|
||||
However, Cryptol's type synonyms are significantly more powerful than
|
||||
C's {\tt typedef}'s, since they can be parameterized by other types,
|
||||
C's {\tt typedef}s, since they can be parameterized by other types,
|
||||
much like in Haskell~\cite{Has98}.
|
||||
|
||||
\todo[inline]{Add a discussion of N-queens or AES or something more compelling
|
||||
@ -2713,7 +2714,7 @@ Type synonyms are either unparameterized (as in {\tt Word8} and {\tt
|
||||
Synonyms may depend upon other synonyms, as in the {\tt CheckedWord}
|
||||
example. Once the synonym is given, it acts as an additional name for
|
||||
the underlying type, making it much easier to read and
|
||||
maintain.
|
||||
maintain.
|
||||
|
||||
For instance, we can write the function that returns the x-coordinate
|
||||
of a point as follows:
|
||||
@ -2726,7 +2727,8 @@ Note that type synonyms, while maintained within the type and value
|
||||
context shown via the \texttt{:browse} command, are
|
||||
\emph{value-based}, not \emph{name-based}. When viewed from the
|
||||
types-as-sets interpretation, two types in Cryptol are synonymous if
|
||||
their values happen to be equal.
|
||||
their values happen to be equal.
|
||||
\todo[inline]{The above paragraph is very confusing!}
|
||||
|
||||
For example, consider the following declarations:
|
||||
%% not "code" to avoid conflicting with previous Word8
|
||||
@ -2748,6 +2750,7 @@ Within this type context, while six \emph{names} are declared, only
|
||||
\emph{two} types are declared (\texttt{[8]} and the pair \texttt{([8],
|
||||
[8])}. Likewise, the function types of \texttt{foo} and \texttt{bar}
|
||||
are identical, thus \texttt{bar} can call \texttt{foo}.
|
||||
\todo[inline]{Also very confusing! What does it mean that two types are declared?}
|
||||
|
||||
\begin{Exercise}\label{ex:tsyn:1}
|
||||
Define a type synonym for 3-dimensional points and write a function
|
||||
@ -2776,7 +2779,7 @@ predefined in Cryptol:
|
||||
type String n = [n]Char
|
||||
type Word n = [n]
|
||||
\end{Verbatim}
|
||||
For instance, a {\tt String n} is simply a sequence of precisely n
|
||||
For instance, a {\tt String n} is simply a sequence of precisely $n$
|
||||
8-bit words.\indTSWord\indTSString\indTSBool
|
||||
|
||||
\todo[inline]{Discussion of \texttt{String} as a type synonym is an
|
||||
@ -2795,12 +2798,12 @@ Type classes are a way of describing behaviors shared by multiple
|
||||
types. As an example, consider the type of the function {\tt ==}:
|
||||
\begin{Verbatim}
|
||||
Cryptol> :t (==)
|
||||
== : {a} (Cmp a) => a -> a -> Bit
|
||||
(==) : {a} (Cmp a) => a -> a -> Bit
|
||||
\end{Verbatim}
|
||||
|
||||
This operator type is interpreted ``equality is an operator that takes
|
||||
two objects of any single type that can be compared and returns a
|
||||
Bit.''
|
||||
Bit.''
|
||||
|
||||
Cryptol defines exactly two basic type classes: {\tt Cmp} and {\tt
|
||||
Arith}. These appear in the type signature of operators and
|
||||
@ -2812,9 +2815,11 @@ The \texttt{Cmp} typeclass includes the binary relation operators
|
||||
\texttt{<}, \texttt{>}, \texttt{<=}, \texttt{>=}, \texttt{==}, and
|
||||
\texttt{!=}, as well as the binary functions \texttt{min} and
|
||||
\texttt{max}. Note that equality is defined on function types (i.e.,
|
||||
\texttt{{a b} (Cmp b) => (a -> b) -> (a -> b) -> a -> Bit}). Unlike
|
||||
\texttt{\{a b\} (Cmp b) => (a -> b) -> (a -> b) -> a -> Bit}). Unlike
|
||||
in many other languages, equality and comparison are bundled into a
|
||||
single typeclass.
|
||||
\todo[inline]{``many'' other languages? Like what?}
|
||||
\todo[inline]{``equality is defined on function types'' is misleading, can't use == for this.}
|
||||
|
||||
The \texttt{Arith} typeclass include the binary operators \texttt{+},
|
||||
\texttt{-}, \texttt{*}, \texttt{/}, \verb+%+, \verb+^^+, as well
|
||||
@ -2852,7 +2857,7 @@ in functions such as {\tt groupBy}, that when you call a function in
|
||||
Cryptol, there are two kinds of parameters you can pass: {\it value
|
||||
variables} and {\it type variables}.
|
||||
|
||||
Consider the \emph{groupBy} function that we previously examined in
|
||||
Consider the \texttt{groupBy} function that we previously examined in
|
||||
\autoref{ex:poly:groupBy}. Recall that \texttt{groupBy}'s type is:
|
||||
\begin{verbatim}
|
||||
groupBy : {each, parts, elem} (fin each) =>
|
||||
@ -2910,8 +2915,8 @@ to our example is:
|
||||
Note the use of an underscore in order to pass \texttt{3} in the
|
||||
second position. Positional arguments are most often used when the
|
||||
type argument is the first argument and when the name of the argument
|
||||
does not add clarity. The {\tt groupBy\Verb|`{_,3}|} is not as self-
|
||||
explanatory as {\tt groupBy\Verb|`{parts=3}|}. On the other hand, our
|
||||
does not add clarity. The {\tt groupBy\Verb|`{_,3}|} is not as
|
||||
self-explanatory as {\tt groupBy\Verb|`{parts=3}|}. On the other hand, our
|
||||
use of positional arguments to {\tt take} in previous chapters is very
|
||||
clear, as in:
|
||||
\begin{Verbatim}
|
||||
@ -2921,7 +2926,7 @@ clear, as in:
|
||||
|
||||
\begin{tip}
|
||||
Cryptol programs that use named arguments are more maintainable and
|
||||
robust during program evolution. E.g., you can reorder paramters or
|
||||
robust during program evolution. E.g., you can reorder parameters or
|
||||
refactor function definitions much more easily if invocations of
|
||||
those functions use named, rather than positional, arguments.
|
||||
\end{tip}
|
||||
@ -2934,11 +2939,11 @@ clear, as in:
|
||||
\label{sec:type-context-vs}
|
||||
|
||||
You have seen, in the discussion of type variables above, that Cryptol
|
||||
has two kinds of variables -- type variables and value variables. Type
|
||||
has two kinds of variables---type variables and value variables. Type
|
||||
variables normally show up in type signatures, and value variables
|
||||
normally show up in function definitions. Sometimes you may want to
|
||||
use a type variable in a context where value variables would normally
|
||||
be used. To do this, use the backtick character {\tt \Verb|`|}.
|
||||
be used. To do this, use the backtick character {\tt \Verb|`|}.
|
||||
|
||||
The definition of the built-in {\tt width} function is a good example
|
||||
of the use of backtick:
|
||||
@ -2968,12 +2973,12 @@ of the use of backtick:
|
||||
right thing.
|
||||
\end{tip}
|
||||
|
||||
The bounds in a finite sequence literal (such as {\tt [1 .. 10]}) in
|
||||
The bounds in a finite sequence literal (such as \texttt{[1 ..\ 10]}) in
|
||||
Cryptol are type-level values because the length of a sequence is part
|
||||
of its type. Only type-level values can appear in a finite sequence
|
||||
definition. You cannot write {\tt [a .. b]} where either {\tt a} or
|
||||
{\tt b} are arguments to a function. On the other hand, an infinite
|
||||
sequence's type is fixed ({\tt [inf]a}), so the initial value in an
|
||||
definition. You cannot write \texttt{[a ..\ b]} where either \texttt{a} or
|
||||
\texttt{b} are arguments to a function. On the other hand, an infinite
|
||||
sequence's type is fixed (\texttt{[inf]a}), so the initial value in an
|
||||
infinite sequence can be a runtime variable or a type variable, but
|
||||
type variables are escaped here using a {\tt \Verb|`|}.
|
||||
|
||||
@ -3008,7 +3013,7 @@ syntax for this should look familiar:
|
||||
\end{code}
|
||||
|
||||
This defines a function that takes two bytes as input, and returns their sum.
|
||||
Note that the use of {\tt( )}'s is mandatory.
|
||||
Note that the use of parentheses \texttt{( )} is mandatory.
|
||||
|
||||
Here is a more interesting example:
|
||||
\begin{code}
|
||||
@ -3024,7 +3029,7 @@ Here is a more interesting example:
|
||||
When a cryptographic specification gets very large it can make sense
|
||||
to decompose its functions into modules.\indModuleSystem\indImport
|
||||
Doing this well encourages
|
||||
code re-use, so it's a generally good thing to do. Cryptol's module
|
||||
code reuse, so it's a generally good thing to do. Cryptol's module
|
||||
system is simple and easy to use. Here's a quick overview:
|
||||
|
||||
A module's name should be the same as the filename the module is
|
||||
@ -3057,7 +3062,7 @@ that include it by using the \verb+private+ keyword, like this:\indPrivate
|
||||
|
||||
As you can tell, by default definitions are exported to including modules.
|
||||
|
||||
For large project it can be convenient to place modules in a directory
|
||||
For a large project it can be convenient to place modules in a directory
|
||||
structure. In this case, the directory structure becomes part of the modules'
|
||||
names. For example, when placing \verb+SHA3.cry+ in the \verb+Hash+ directory and
|
||||
accessing it from \verb+HMAC.cry+ you would need to name the modules
|
||||
@ -3077,8 +3082,7 @@ module Hash::SHA3 where
|
||||
import Hash::SHA3
|
||||
import Cryptol::Extras
|
||||
|
||||
hmac : {keySize, msgSize} (fin keySize, fin msgSize) => [keySize] -> [msgSize]
|
||||
-> [512]
|
||||
hmac : {keySize, msgSize} (fin keySize, fin msgSize) => [keySize] -> [msgSize] -> [512]
|
||||
hmac k m = sha3 (ko # sha3 (ki # m))
|
||||
where ko = zipWith (^) kFull (join (repeat 0x5c))
|
||||
ki = zipWith (^) kFull (join (repeat 0x36))
|
||||
|
Loading…
Reference in New Issue
Block a user