@@ -1139,7 +1139,251 @@ \subsection{When To Use In-Place Updates}
11391139\section {Modules }
11401140\label {sec:modules }
11411141
1142- Yet to be written...
1142+ When most programmers think of module systems, they think of rather
1143+ utilitarian systems for namespace control and splitting programs
1144+ across multiple files. And in most languages, the module system is
1145+ indeed little more than this. But in Futhark, we have adopted an
1146+ ML-style higher-order module system that permits \textit {abstraction }
1147+ over modules. The module system is not just a method for organising
1148+ Futhark programs, but also the sole facility for writing generic code.
1149+
1150+ \subsection {Simple Modules }
1151+
1152+ At the most basic level, a \textit {module } (called a \textit {struct }
1153+ in Standard ML) is merely a collection of declarations
1154+
1155+ \ begin{lstlisting}
1156+ module AddI32 = {
1157+ type t = i32
1158+ fun add (x: t) (y: t): t = x + y
1159+ val zero: t = 0
1160+ }
1161+ \end {lstlisting }
1162+
1163+ Now, \texttt {AddI32.t } is an alias for the type \texttt {i32 }, and
1164+ \texttt {Addi32.add } is a function that adds two values of type
1165+ \texttt {i32 }. The only peculiar thing about this notation is the
1166+ equal sign before the opening brace. The declaration above is
1167+ actually a combination of a *module binding*
1168+
1169+ \ begin{lstlisting}
1170+ module ADDI32 = ...
1171+ \end {lstlisting }
1172+
1173+ And a \textit {module expression }
1174+
1175+ \ begin{lstlisting}
1176+ {
1177+ type t = i32
1178+ fun add (x: t) (y: t): t = x + y
1179+ val zero: t = 0
1180+ }
1181+ \end {lstlisting }
1182+
1183+ In this case, the module expression is just some declarations enclosed
1184+ in curly braces. But, as the name suggests, a module expression is
1185+ just some expression that returns a module. A module expression is
1186+ syntactically and conceptually distinct from a regular value
1187+ expression, but serves much the same purpose. The module language is
1188+ designed such that evaluation a module expression can always be done
1189+ at compile time.
1190+
1191+ Apart from a sequence of declarations, a module expression can also be
1192+ merely the name of another module
1193+
1194+ \ begin{lstlisting}
1195+ module Foo = AddInt32
1196+ \end {lstlisting }
1197+
1198+ Now every name defined in \texttt {AddInt32 } is also available in
1199+ \texttt {Foo }. At compile-time, only a single version of the
1200+ \texttt {add } function is defined.
1201+
1202+ \subsection {Module Types }
1203+
1204+ What we have seen so far is nothing more than a simple namespacing
1205+ mechanism. The ML module system only becomes truly powerful once we
1206+ introduce module types and parametric modules (in Standard ML, these
1207+ are called \textit {signatures } and \textit {functors }).
1208+
1209+ A module type is the counterpart to a value type. It describes which
1210+ names are defined, and as what. We can define a module type that
1211+ describes \texttt {AddInt32 }
1212+
1213+ \ begin{lstlisting}
1214+ module type Int32Adder = {
1215+ type t = i32
1216+ val add: t -> t -> t
1217+ val zero: t
1218+ }
1219+ \end {lstlisting }
1220+
1221+ As with modules, we have the notion of a \textit {module type expression }. In
1222+ this case, the module type expression is a sequence of \textit {specs }
1223+ enclosed in curly braces. A spec is a requirement of how some name
1224+ must be defined: as a value (including functions) of some type, as a
1225+ type abbreviation, or as an abstract type (which we will return to
1226+ later).
1227+
1228+ We can assert that some module implements a specific module type via
1229+ module type ascription
1230+
1231+ \ begin{lstlisting}
1232+ module Foo = AddInt32 : Int32Adder
1233+ \end {lstlisting }
1234+
1235+ Syntactical sugar that allows us to move the module type to the left
1236+ of the equal sign makes a common case look smoother
1237+
1238+ \ begin{lstlisting}
1239+ module AddInt32: Int32Adder = {
1240+ ...
1241+ }
1242+ \end {lstlisting }
1243+
1244+ When we are ascribing a module with a module type, the module type
1245+ functions as a filter, removing anything not explicitly mentioned in
1246+ the module type
1247+
1248+ \ begin{lstlisting}
1249+ module Bar = AddInt32 : { type t = int
1250+ val zero: t }
1251+ \end {lstlisting }
1252+
1253+ An attempt to access \texttt {Bar.add } will result in a compilation
1254+ error, as the ascription has hidden it. This is known as an
1255+ \textit {opaque } ascription, because it obscures anything not
1256+ explicitly mentioned in the module type. The module systems in
1257+ Standard ML and OCaml support both opaque and \textit {transparent }
1258+ ascription, but in Futhark we support only the former. This example
1259+ also demonstrates the use of an anonymous module type. Module types
1260+ work much like structural types known from e.g. Go ("compile-time duck
1261+ typing"), and are named only for convenience.
1262+
1263+ We can use type ascription with abstract types to hide the definition
1264+ of a type from the users of a module
1265+
1266+ \ begin{lstlisting}
1267+ module Speeds: { type thing
1268+ val car: thing
1269+ val plane: thing
1270+ val futhark: thing
1271+ val speed: thing -> int } = {
1272+ type thing = int
1273+
1274+ val car: thing = 0
1275+ val plane: thing = 1
1276+ val futhark: thing = 2
1277+
1278+ fun speed (x: thing): int =
1279+ if x == car then 120
1280+ else if x == plane then 800
1281+ else if x == futhark then 10000
1282+ else 0 -- will never happen
1283+ }
1284+ \end {lstlisting }
1285+
1286+ The (anonymous) module type asserts that a distinct type \texttt {thing }
1287+ must exist, but does not mention its definition. There is no way for
1288+ a user of the \texttt {Speeds } module to do anything with a value of type
1289+ \texttt {Speeds.thing } apart from passing it to \texttt {Speeds.speed } (except
1290+ putting it in an array or tuple, or returning it from a function).
1291+ Its definition is entirely abstract. Furthermore, no values of type
1292+ \texttt {Speeds.thing } exist except those that are created by the \texttt {Speeds }
1293+ module.
1294+
1295+ \subsection {Parametric Modules }
1296+
1297+ While module types serve some purpose for namespace control and
1298+ abstraction, their most interesting use is in the definition of
1299+ parametric modules. A parametric module is conceptually
1300+ equivalent to a function. Where a function takes a value as input and
1301+ produces a value, a parametric module takes a module and produces a
1302+ module. For example, given a module type
1303+
1304+ \ begin{lstlisting}
1305+ module type Monoid = {
1306+ type t
1307+ val add: t -> t -> t
1308+ val zero: t
1309+ }
1310+ \end {lstlisting }
1311+
1312+ We can define a parametric module that accepts a module satisfying
1313+ the \texttt {Monoid } module type, and produces a module containing a
1314+ function for collapsing an array
1315+
1316+ \ begin{lstlisting}
1317+ module Sum(M: Monoid) = {
1318+ fun sum (a: []M.t): M.t =
1319+ reduce M.add M.zero a
1320+ }
1321+ \end {lstlisting }
1322+
1323+ There is an implied assumption here, which is not captured by the type
1324+ system: the function \texttt {add } must be associative and have
1325+ \texttt {zero } as its neutral element. These constraints are from the
1326+ parallel semantics of \texttt {reduce }, and the algebraic concept of a
1327+ \textit {monoid }. Note that in \texttt {Monoid }, no definition is given
1328+ of the type \texttt {t } - we only assert that there must be some type
1329+ \texttt {t }, and that certain operations are defined for it.
1330+
1331+ We can use the parametric module \texttt {Sum } thus
1332+
1333+ \ begin{lstlisting}
1334+ module SumI32s = Sum(AddInt32)
1335+ \end {lstlisting }
1336+
1337+ We can now refer to the function \texttt {SumI32s.sum }, which has type
1338+ \texttt {[]i32 -> i32 }. The type is only abstract inside the definition of
1339+ the parametric module. We can instantiate \texttt {Sum } again with
1340+ another module; this one anonymous
1341+
1342+ \ begin{lstlisting}
1343+ module Prod64s = Sum({
1344+ type t = 64
1345+ fun (x: f64) (y: f64): f64 = x * y
1346+ fun zero: f64 = 1.0
1347+ })
1348+ \end {lstlisting }
1349+
1350+ The function \texttt {Prodf64s.sum } has type \texttt {[]f64 -> f64 }, and computes
1351+ the product of an array of numbers (we should probably have picked a
1352+ more generic name than \texttt {sum } for this function).
1353+
1354+ Operationally, each application of a parametric module results in
1355+ its definition being duplicated and references to the module parameter
1356+ replace by references to the concrete module argument. This is quite
1357+ similar to how C++ templates are implemented. Indeed, parametric
1358+ modules can be seen as a simplified variant with no specialisation,
1359+ and with module types to ensure rigid type checking. In C++, a
1360+ template is type-checked when it is instantiated, whereas a
1361+ parametric module is type-checked when it is defined.
1362+
1363+ Parametric modules, like other modules, can contain more than one
1364+ declaration. This is useful for giving related functionality a common
1365+ abstraction, for example to implement linear algebra operations that
1366+ are polymorphic over the type of scalars. This example uses an
1367+ anonymous module type for the module parameter, and the \texttt {open }
1368+ declaration, which brings the names from a module into the current
1369+ scope
1370+
1371+ \ begin{lstlisting}
1372+ module Linalg(M: {
1373+ type scalar
1374+ val zero: scalar
1375+ val add: scalar -> scalar -> scalar
1376+ val mul: scalar -> scalar -> scalar
1377+ }) = {
1378+ open M
1379+
1380+ fun dotprod (xs: [n]scalar) (ys: [n]scalar): scalar =
1381+ reduce add zero (zipWith mul xs ys)
1382+
1383+ fun matmul (xss: [n][p]scalar) (yss: [p][m]scalar): [n][m]scalar =
1384+ map (\xs -> map (dotprod xs) (transpose yss)) xss
1385+ }
1386+ \end {lstlisting }
11431387
11441388\section {Benchmarking }
11451389\label {sec:benchmarking }
@@ -2413,4 +2657,5 @@ \chapter{Tool References}
24132657% %% Local Variables:
24142658% %% mode: latex
24152659% %% TeX-master: t
2660+ % %% TeX-engine: luatex
24162661% %% End:
0 commit comments