Monadic Dynamical Systems in C++ with Concepts and in Haskell
Monadic Dynamical Systems in C++ with Concepts and in Haskell
Monadic Dynamical Systems in C++ with Concepts and in Haskell
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
<strong>Monadic</strong> <strong>Dynamical</strong> <strong>Systems</strong><br />
<strong>in</strong> <strong>C++</strong> <strong>with</strong> <strong>Concepts</strong> <strong>and</strong> <strong>in</strong> <strong>Haskell</strong><br />
Daniel L<strong>in</strong>cke 1,∗ , Patrik Jansson b , Marc<strong>in</strong> Zalewski c , Cezar Ionescu 1<br />
a Potsdam Institute for Climate Impact Research, Potsdam, Germany.<br />
b Chalmers University of Technology & University of Gothenburg, Gothenburg, Sweden.<br />
c Indiana University, Bloom<strong>in</strong>gton, USA.<br />
Abstract<br />
In scientific programm<strong>in</strong>g, the implementation of a computational model goes h<strong>and</strong> <strong>in</strong><br />
h<strong>and</strong> <strong>with</strong> a deep analysis of the underly<strong>in</strong>g doma<strong>in</strong>. Software developers <strong>and</strong> doma<strong>in</strong><br />
experts work together to develop a common underst<strong>and</strong><strong>in</strong>g <strong>and</strong> a (possibly executable)<br />
specification. Such a specification should be easy to underst<strong>and</strong> <strong>and</strong> serve as a sketch<br />
for an implementation <strong>in</strong> a high-performance language. In this paper, we describe<br />
a doma<strong>in</strong> us<strong>in</strong>g <strong>Haskell</strong> as a modell<strong>in</strong>g language <strong>and</strong> then we derive a generic implementation<br />
framework from the <strong>Haskell</strong> model. To achieve this, we transform functional<br />
<strong>Haskell</strong> constructs describ<strong>in</strong>g the doma<strong>in</strong> notions <strong>in</strong>to a hierarchy of concepts, generic<br />
algorithms, <strong>and</strong> generic constructors. Our approach is flexible: we can implement a library<br />
based on these concepts <strong>in</strong> every language which supports concept-based generic<br />
programm<strong>in</strong>g.<br />
In particular, we beg<strong>in</strong> <strong>with</strong> the doma<strong>in</strong> of vulnerability assessment. We start <strong>with</strong><br />
analysis of the doma<strong>in</strong>, <strong>and</strong> we provide a high-level executable model based on dynamical<br />
monadic systems. Then we systematically translate the model <strong>in</strong>to a generic<br />
concept-based library. Our approach is demonstrated by a translation <strong>in</strong>to <strong>C++</strong>, but also<br />
sketch how to reimplement our library <strong>in</strong> <strong>Haskell</strong> us<strong>in</strong>g the same pr<strong>in</strong>ciples.<br />
Keywords: generic programm<strong>in</strong>g, functional programm<strong>in</strong>g, vulnerability assessment<br />
1. Introduction<br />
The road from a doma<strong>in</strong> of scientific knowledge to an efficient implementation<br />
is long <strong>and</strong> perilous, often result<strong>in</strong>g <strong>in</strong> an implementation that bears little apparent<br />
resemblance to the doma<strong>in</strong>. Still, the practitioners of high-performance comput<strong>in</strong>g are<br />
will<strong>in</strong>g to pay the price of overwhelm<strong>in</strong>gly low-level implementations to guarantee<br />
performance. In the current day <strong>and</strong> age, however, it is possible to <strong>in</strong>crease the level of<br />
abstraction by apply<strong>in</strong>g generic programm<strong>in</strong>g techniques to provide a high-level library<br />
∗ Correspond<strong>in</strong>g author<br />
Email addresses: daniel.l<strong>in</strong>cke@pik-potsdam.de (Daniel L<strong>in</strong>cke), patrikj@chalmers.se (Patrik<br />
Jansson), zalewski@osl.iu.edu (Marc<strong>in</strong> Zalewski), ionescu@pik-potsdam.de (Cezar Ionescu)<br />
Prepr<strong>in</strong>t submitted to Science of Computer Programm<strong>in</strong>g March 1, 2011
for a doma<strong>in</strong> that allows structured use of exist<strong>in</strong>g, efficient code. In this paper, <strong>in</strong><br />
particular, we show how to first describe a doma<strong>in</strong> <strong>in</strong> a high-level functional style, close<br />
to mathematical notation but executable, <strong>and</strong>, then, transform this description <strong>in</strong>to a<br />
strongly generic library that corresponds closely to the <strong>in</strong>itial description. Specifically,<br />
we present the process by which we derived a generic <strong>C++</strong> (Stroustrup, 1997) library<br />
for vulnerability assessment (vulnerability <strong>in</strong> the context of environmental sciences).<br />
The concept of “vulnerability” plays an important role <strong>in</strong> many research fields, <strong>in</strong>clud<strong>in</strong>g<br />
climate change research (Adger, 2006). As we discuss <strong>in</strong> Sect. 2, there is no<br />
unique def<strong>in</strong>ition of this term. However, there is a simple common structure underly<strong>in</strong>g<br />
the def<strong>in</strong>itions <strong>in</strong> the usage of “vulnerability”, which can be shortly described as measur<strong>in</strong>g<br />
the possible harm for a given system. <strong>Systems</strong> may be of very different natures,<br />
but it turns out that the differences can be captured by the idea of monadic dynamical<br />
systems that hides the particulars of a system beh<strong>in</strong>d a curta<strong>in</strong> of abstraction.<br />
Our <strong>C++</strong> library for monadic systems is derived from the high-level description <strong>in</strong><br />
<strong>Haskell</strong> (Peyton Jones, 2003), given by Ionescu (2009) <strong>in</strong> his formalisation of vulnerability<br />
done at the Potsdam Institute for Climate Impact Research. Ionescu relies on<br />
functional features of <strong>Haskell</strong>, such as function types <strong>and</strong> type constructors, to represent<br />
the underly<strong>in</strong>g mathematical notions of, among others, functors, coalgebras, monads,<br />
<strong>and</strong>, crucially, of monadic dynamical systems, which we <strong>in</strong>troduce <strong>and</strong> expla<strong>in</strong> <strong>in</strong><br />
Sect. 2.3. While his description can be executed, its design is focused on exposition of<br />
ideas <strong>and</strong> not on efficiency. Furthermore, the description is not generic enough to be<br />
applied <strong>in</strong> a practical sett<strong>in</strong>g of exist<strong>in</strong>g implementations, tool sets, <strong>and</strong> so on.<br />
Our library ma<strong>in</strong>ta<strong>in</strong>s the abstract, high-level correspondence <strong>with</strong> the doma<strong>in</strong> notions<br />
<strong>in</strong>troduced by Ionescu but it makes efficient implementations possible by provid<strong>in</strong>g<br />
a generic <strong>in</strong>terface for use of high-performance components. We are able to achieve<br />
the abstraction by bas<strong>in</strong>g the libraries on concepts, a well known term <strong>in</strong> generic programm<strong>in</strong>g.<br />
A concept is an abstract specification of a set of (tuples of) types (Bernardy<br />
et al., 2010). While <strong>in</strong> <strong>Haskell</strong> concepts are provided by means of type classes (Wadler<br />
<strong>and</strong> Blott, 1989), <strong>in</strong> <strong>C++</strong> they are still an experimental language feature called <strong>C++</strong>concepts<br />
(Gregor et al., 2006, 2008c). We use concepts to specify three k<strong>in</strong>ds of components<br />
from our application doma<strong>in</strong>:<br />
• a conceptual framework specify<strong>in</strong>g concepts for functional constructs, like functions,<br />
functors, monads, <strong>and</strong> so on;<br />
• parameterised types, themselves “typed” by concepts, that represent doma<strong>in</strong> constructs<br />
<strong>and</strong> comb<strong>in</strong>ators;<br />
• <strong>and</strong>, f<strong>in</strong>ally, generic functions represent<strong>in</strong>g the algorithms applicable <strong>in</strong> a given<br />
doma<strong>in</strong>.<br />
These components provide a generic, algorithmic description of a doma<strong>in</strong>. The user<br />
of our library must then plug <strong>in</strong> his/her complex data structures, but that is done only<br />
once for each concept, rather than for any possible comb<strong>in</strong>ation required by every<br />
comb<strong>in</strong>ator or algorithm. As an alternative, we provide some simple data structures<br />
that are meant for <strong>Haskell</strong>-like prototyp<strong>in</strong>g rather than a full-blown implementation.<br />
2
Functions<br />
Function Fun ∼ a -> b : describes general unary function types<br />
Type Constructors<br />
ConstructorType T ∼ f :: *->* : the type T is a unary type constructor<br />
SameTypeConstructor<br />
T1 ∼ f :: *->*, T2 ∼ f :: *->* : two types represent the same<br />
type constructor<br />
Functors <strong>and</strong> Monads<br />
Functor<br />
the type T is a unary functor type<br />
: ConstructorType<br />
Monad<br />
the type T is a unary monad type<br />
: ConstructorType<br />
Figure 1: Overview of the core concepts of the functional <strong>C++</strong> concepts library. The full library also conta<strong>in</strong>s<br />
concepts like FunctionN <strong>and</strong> FunctorN (for small N) <strong>and</strong> related convenience functions.<br />
Constructors for <strong>Monadic</strong> system<br />
Discrete_<strong>Monadic</strong>_System<br />
Trans ∼ (x -> m x) : a discrete monadic system<br />
∼ Int -> (x -> m x)<br />
is constructed from a given transition function Trans<br />
<strong>Monadic</strong>_System_Input<br />
Trans ∼ i -> (x -> m x), Cont ∼ [i] : an MDS<br />
∼ [i] -> (x -> m x)<br />
<strong>with</strong> <strong>in</strong>put of type [i] is constructed from a given<br />
transition function Trans<br />
Comb<strong>in</strong>ators for <strong>Monadic</strong> system<br />
<strong>Monadic</strong>_<strong>Systems</strong>_Parallel<br />
∼ (i1, i2)-> ((x,y)-> PairM m n (x,y))<br />
Sys_Ser_Function<br />
∼ (i1, i2)-> x -> m x<br />
Sys1 ∼ i1 -> (x -> m x),<br />
Sys2 ∼ i2 -> (y -> n y): : Two monadic systems<br />
are comb<strong>in</strong>ed <strong>in</strong> parallel<br />
Sys1 ∼ i1 -> (x -> m x),<br />
Sys2 ∼ i2 -> (x -> m x) : two monadic systems<br />
<strong>with</strong> the same state space <strong>and</strong> the same monad are<br />
comb<strong>in</strong>ed <strong>in</strong>to a comb<strong>in</strong>ed transition function <strong>with</strong><br />
<strong>in</strong>put<br />
Figure 2: Overview of the ma<strong>in</strong> parametrised types <strong>in</strong> the library<br />
Special Function types<br />
Coalgebra Fun ∼ x -> f x : functions whose codoma<strong>in</strong> is a functor<br />
: Function<br />
application<br />
CoalgebraWithInput Fun ∼ i -> x -> f x : coalgebras <strong>with</strong> an additional<br />
: Function2<br />
<strong>in</strong>put<br />
<strong>Monadic</strong>Coalgebra Fun ∼ x -> m x : functions whose codoma<strong>in</strong> is a monad<br />
: Coalgebra<br />
application<br />
<strong>Monadic</strong>CoalgebraWithInput Fun ∼ i -> x -> m x : monadic coalgebras <strong>with</strong> an<br />
: CoalgebraWithInput additional <strong>in</strong>put<br />
<strong>Monadic</strong> system<br />
<strong>Monadic</strong>System<br />
: Function<br />
Sys ∼ i -> (x -> m x) : Sys is a monadic system<br />
Figure 3: Overview of the ma<strong>in</strong> concepts <strong>in</strong> the <strong>Monadic</strong> systems library<br />
The library for monadic dynamical systems presented <strong>in</strong> this paper consists of two<br />
parts. First, we capture the basic constructs of functional programm<strong>in</strong>g <strong>in</strong> a separate<br />
library called FCPPC (Functional <strong>C++</strong> <strong>with</strong> <strong>Concepts</strong>) (L<strong>in</strong>cke, 2010; L<strong>in</strong>cke <strong>and</strong><br />
Schupp, 2009). In contrast to other exist<strong>in</strong>g libraries for functional <strong>C++</strong> programm<strong>in</strong>g,<br />
like F<strong>C++</strong> (McNamara <strong>and</strong> Smaragdakis, 2004a), our <strong>in</strong>tention is not to provide the<br />
3
whole <strong>Haskell</strong> prelude <strong>in</strong> <strong>C++</strong>. We rather provide a framework of concepts which specifies<br />
types for functional constructs. This library is <strong>in</strong>dependent of the vulnerability<br />
doma<strong>in</strong>, <strong>and</strong> can, or even should, be reused when our approach is used <strong>in</strong> other doma<strong>in</strong>s.<br />
Next, us<strong>in</strong>g the FCPPC library as the base, we capture the constructs from the<br />
doma<strong>in</strong> of monadic dynamical systems. While our library is split <strong>in</strong>to two parts based<br />
on reusability of the components of each part, both parts are derived us<strong>in</strong>g the same<br />
approach <strong>and</strong> both parts consists of the three k<strong>in</strong>ds of components described before.<br />
In order to give an overview of our approach, the core concepts from FCPPC are<br />
outl<strong>in</strong>ed <strong>in</strong> Fig. 1 <strong>and</strong> the core concepts <strong>and</strong> constructors/comb<strong>in</strong>ators of the monadic<br />
systems library are presented <strong>in</strong> Fig. 3 <strong>and</strong> Fig. 2. In both figures the left column shows<br />
the signature of the concepts <strong>and</strong> functions as well as ref<strong>in</strong>ement relations, written <strong>in</strong><br />
<strong>C++</strong> syntax. The right column shows how the parameters of the concept match the<br />
<strong>Haskell</strong> signature (we write C ∼ t for “<strong>C++</strong> type C corresponds to <strong>Haskell</strong> type t”).<br />
Furthermore we give a brief explanation of what the concept or function is <strong>in</strong>tended<br />
to model. The concepts are divided <strong>in</strong>to groups for presentation reasons (the group<strong>in</strong>g<br />
does not imply any hierarchy). In Figs. 1 <strong>and</strong> 3 we do not <strong>in</strong>tend to give a detailed<br />
description of the concepts we use, therefore associated entities are not stated.<br />
A library like our monadic system library is much more complex <strong>and</strong> verbose than<br />
its high-level specification <strong>in</strong> <strong>Haskell</strong> but it is surpris<strong>in</strong>gly similar <strong>and</strong> nimble from<br />
the po<strong>in</strong>t of view of the user. For example, the computation of macro-trajectories (see<br />
Sect. 2.3) is cleanly specified <strong>in</strong> <strong>Haskell</strong> as a function of the follow<strong>in</strong>g type:<br />
1 macro_trj :: (Monad m) => (i -> x -> m x) -> x -> [i] -> [m x]<br />
In the <strong>C++</strong> library functional constructs are lifted to the concept level, <strong>and</strong> the type of<br />
the function has to be translated accord<strong>in</strong>gly (express<strong>in</strong>g sequences <strong>with</strong> <strong>C++</strong>’s iterator<br />
mechanism):<br />
1 template<br />
3 requires<br />
4 std::SameType,<br />
5 std::SameType<br />
6 void<br />
7 macro_trajectory(Mon_Sys sys,<br />
8 Inp_Iter controls_bg, Inp_Iter controls_end,<br />
9 Mon_Sys::Codoma<strong>in</strong>::Doma<strong>in</strong>1 x,<br />
10 Out_Iter& ret);<br />
In <strong>C++</strong>, the type of the <strong>Haskell</strong> macro_trj function must be expressed <strong>in</strong> terms of<br />
concepts. Besides the concept <strong>Monadic</strong>System that is taken form our library, we rely<br />
on concepts from the <strong>C++</strong> st<strong>and</strong>ard library (preceded by the std:: prefix). While a<br />
function like macro_trajectory clearly is more complex from the po<strong>in</strong>t of view of a<br />
library developer, the complexity is hidden when the function is used:<br />
1 macro_trajectory(my_sys, ctrl.beg<strong>in</strong>(), ctrl.end(), <strong>in</strong>it, ret);<br />
The user must declare the necessary modell<strong>in</strong>gs (called “concept maps” <strong>in</strong> <strong>C++</strong> <strong>and</strong><br />
“<strong>in</strong>stances” <strong>in</strong> <strong>Haskell</strong>) that describe how types model the necessary concepts. The decoupl<strong>in</strong>g<br />
of concepts <strong>and</strong> their modell<strong>in</strong>gs makes it possible to use the library <strong>with</strong> the<br />
exist<strong>in</strong>g high-performance implementations while keep<strong>in</strong>g the complexity manageable.<br />
4
This paper is based on an earlier conference paper (L<strong>in</strong>cke et al., 2009). We generalised<br />
the approach by separat<strong>in</strong>g the functional components out <strong>in</strong>to a separate library.<br />
Furthermore we made the approach more widely applicable by transform<strong>in</strong>g the functional<br />
constructs <strong>and</strong> the doma<strong>in</strong> notions <strong>in</strong>to concepts <strong>in</strong> general. With these general<br />
concepts it is possible to implement the result<strong>in</strong>g library <strong>in</strong> any language which provides<br />
an implementation of concepts. From the po<strong>in</strong>t of view from the library, we<br />
additionally explored questions of system comb<strong>in</strong>ation <strong>and</strong> present some useful comb<strong>in</strong>ators<br />
for monadic dynamical systems.<br />
In the rema<strong>in</strong>der of the paper, we outl<strong>in</strong>e the progression from the doma<strong>in</strong> to an<br />
efficient implementation by first express<strong>in</strong>g doma<strong>in</strong> notions <strong>in</strong> a functional form, <strong>and</strong><br />
then implement<strong>in</strong>g them us<strong>in</strong>g our library of functional concepts, This is illustrated by<br />
our particular path from the doma<strong>in</strong> of monadic systems <strong>in</strong> the context of vulnerability<br />
assessment to our <strong>C++</strong> library for monadic systems. In Sect. 2, we present the concept<br />
of vulnerability as used <strong>in</strong> the climate change community <strong>and</strong> its mathematical formalisation<br />
<strong>in</strong> <strong>Haskell</strong>. We show that different k<strong>in</strong>ds of dynamical systems are <strong>in</strong>volved <strong>in</strong><br />
vulnerability studies <strong>and</strong> expla<strong>in</strong> why monadic dynamical systems are an appropriate<br />
model for these systems. Sect. 3.1 shows how functional constructs like functions,<br />
functors <strong>and</strong> monads can be expressed by concepts <strong>and</strong> show a <strong>C++</strong> implementation of<br />
them. Sect. 3.2 describes how the doma<strong>in</strong> specific constructs (concepts, parametrised<br />
types <strong>and</strong> functions) of the monadic systems doma<strong>in</strong> are provided <strong>in</strong> <strong>C++</strong> <strong>and</strong> Sect. 3.3<br />
shows how the library can be used. Sect. 4 expla<strong>in</strong>s how the concepts can be implemented<br />
us<strong>in</strong>g type classes <strong>in</strong> <strong>Haskell</strong>. In Sect. 5 we survey related work <strong>and</strong> <strong>in</strong> Sect. 6<br />
we discuss our approach <strong>and</strong> present ideas how to further generalise it.<br />
1.1. Prelim<strong>in</strong>aries<br />
We use <strong>Haskell</strong> code for describ<strong>in</strong>g the mathematical model, concepts for describ<strong>in</strong>g<br />
the conceptual framework <strong>and</strong> <strong>C++</strong> code for describ<strong>in</strong>g the actual implementation.<br />
Here we give a very short description of some of the notation used. It is worth not<strong>in</strong>g<br />
already from the start that :: is used <strong>in</strong> two different ways: <strong>in</strong> <strong>Haskell</strong> it is the “has<br />
type” keyword, while <strong>in</strong> <strong>C++</strong> it is the “scope resolution” operator.<br />
1.1.1. Functional modell<strong>in</strong>g<br />
Any pure functional language <strong>with</strong> appropriate support of generic programm<strong>in</strong>g<br />
could be used for our mathematical modell<strong>in</strong>g of monadic dynamical systems. Such<br />
languages usually have clean syntax <strong>and</strong> stay close to the orig<strong>in</strong>al mathematical notation<br />
from which they borrow their expressive type systems <strong>and</strong> algebraic type classes.<br />
We picked <strong>Haskell</strong> (Peyton Jones, 2003), <strong>with</strong>out any of the language extensions, for<br />
specification of the mathematical model. As usual <strong>in</strong> <strong>Haskell</strong> we denote function application<br />
by juxtaposition: f a denotes the application of f to a, parentheses are not<br />
needed. Function composition is (.) :: (b ->c) -> (a -> b) -> (a -> c) <strong>and</strong> for<br />
Kleisli composition we use ( (a -> m b) -> (a -> m c)<br />
We use two recursion operators for lists—foldr <strong>and</strong> scanr—which are best <strong>in</strong>troduced<br />
by example. If we def<strong>in</strong>e sum = foldr (+) 0 <strong>and</strong> sums = scanr (+) 0 then<br />
sum [3,2,1] is 6 <strong>and</strong> sums [3,2,1] are the partial sums [6,3,1,0]. Follow<strong>in</strong>g a similar<br />
pattern we use foldr to compose lists of monadic actions:<br />
5
1 mcompose :: Monad m => [x -> m x] -> (x -> m x)<br />
2 mcompose = foldr ( [a] which creates a list by repetition<br />
of a given element. For test<strong>in</strong>g we write predicates (parametrised test cases) as<br />
normal <strong>Haskell</strong> functions run by QuickCheck (Claessen <strong>and</strong> Hughes, 2000). F<strong>in</strong>ally we<br />
use the type constructor SimpleProb for probability distributions <strong>with</strong> f<strong>in</strong>ite support.<br />
1 type Prob = Double<br />
2 newtype SimpleProb a = SP [(a, Prob)] deriv<strong>in</strong>g Show<br />
The <strong>Haskell</strong> type system is complex enough to have has its own type system: k<strong>in</strong>ds.<br />
Base types, like Bool, are of k<strong>in</strong>d * while a parametrised type like SimpleProb has k<strong>in</strong>d<br />
*->*.<br />
1.1.2. <strong>Concepts</strong><br />
For concepts we stick to the term<strong>in</strong>ology from (Bernardy et al., 2010; Garcia et al.,<br />
2007a). We use the term concept for an abstract specification of a set of (tuples of)<br />
types, where the arity of a concept is the size of the tuple (the number of type parameters).<br />
Semantically, a concept is a predicate over types. When a tuple of types satisfies<br />
this predicate, we say that it is a model for the concept. A concept has a number of<br />
associated entities (often called members): values, functions, or types. Def<strong>in</strong>itions for<br />
these entities are provided <strong>in</strong> the modell<strong>in</strong>gs (model declarations). In addition, a concept<br />
can state requirements for its types. Modell<strong>in</strong>gs are type-checked tak<strong>in</strong>g these<br />
requirements <strong>in</strong>to account. <strong>Concepts</strong> can ref<strong>in</strong>e each other. A concept C 1 ref<strong>in</strong>es another<br />
concept C 2 if C 1 implies C 2 , that means the associated entities of C 2 are available<br />
whenever the entities of C 1 are available. In this paper we describe concepts literally<br />
by list<strong>in</strong>g their associated entities.<br />
1.1.3. <strong>Concepts</strong> <strong>in</strong> <strong>C++</strong><br />
<strong>C++</strong> implements concepts by the experimental language feature <strong>C++</strong>-concepts<br />
(Gregor et al., 2006, 2008c). <strong>Concepts</strong> can be used to constra<strong>in</strong> the type parameters<br />
of templates us<strong>in</strong>g the requires keyword. Templates (basically pieces of code<br />
parametrised by types or values) are the generic programm<strong>in</strong>g technique of <strong>C++</strong>. Concept<br />
modell<strong>in</strong>g <strong>in</strong> <strong>C++</strong> is done by concept maps which are used to b<strong>in</strong>d names dependent<br />
on type parameters to the implementations provided by the user (Gregor et al., 2006,<br />
2008c).<br />
The follow<strong>in</strong>g snippet of code is a complete example of us<strong>in</strong>g concepts:<br />
1 concept Function {<br />
2 typename Doma<strong>in</strong>1;<br />
3 typename Codoma<strong>in</strong>;<br />
4<br />
5 Codoma<strong>in</strong> operator () (Fun, Doma<strong>in</strong>1);<br />
6 };<br />
7<br />
8 template<br />
9 requires<br />
10 Function,<br />
6
11 std::SameType<br />
12 Fun::Codoma<strong>in</strong> twice(Fun fun, Fun::Doma<strong>in</strong>1 x) {<br />
13 return fun(fun(x));<br />
14 }<br />
15<br />
16 struct Increment {<br />
17 typedef Int Doma<strong>in</strong>1;<br />
18 typedef Int Codoma<strong>in</strong>;<br />
19<br />
20 Codoma<strong>in</strong> operator()(Doma<strong>in</strong>1 x) { return x++; }<br />
21 };<br />
22<br />
23 concept_map Function {<br />
24 typedef Increment::Doma<strong>in</strong>1 Doma<strong>in</strong>1;<br />
25 typedef Increment::Codoma<strong>in</strong> Codoma<strong>in</strong>;<br />
26 }<br />
27<br />
28 Increment <strong>in</strong>c;<br />
29 <strong>in</strong>t x = twice(<strong>in</strong>c,0);<br />
The concept Function, def<strong>in</strong>ed from L<strong>in</strong>e 1, def<strong>in</strong>es a predicate on a s<strong>in</strong>gle type <strong>and</strong><br />
requires two associated type Doma<strong>in</strong>1 <strong>and</strong> Codoma<strong>in</strong> <strong>and</strong> an application operator ().<br />
Thus, the concept specifies function types. It is then used, on L<strong>in</strong>e 10, to constra<strong>in</strong> the<br />
sole type parameter of the twice function. The requirement ensures, that the parameter<br />
type is a function type. The second requirement (L<strong>in</strong>e 11) states that this function<br />
type is a homogeneous function, which makes it possible to apply the function two<br />
times. The user-def<strong>in</strong>ed type Increment, def<strong>in</strong>ed <strong>in</strong> L<strong>in</strong>es 16–21, is than declared to<br />
model Function, on L<strong>in</strong>e 23. In the model declaration the b<strong>in</strong>d<strong>in</strong>gs for the associated<br />
types are provided (L<strong>in</strong>es 24–25) while the def<strong>in</strong>ition of the associated operator is<br />
not given explicitly. In such situations, the compiler is required to attempt to f<strong>in</strong>d a<br />
match<strong>in</strong>g def<strong>in</strong>ition <strong>in</strong> the context, <strong>and</strong>, <strong>in</strong> this case, it f<strong>in</strong>ds the application operator<br />
of Increment. F<strong>in</strong>ally, the usage of concept-constra<strong>in</strong>ed twice is demonstrated on<br />
L<strong>in</strong>e 29: the application twice(<strong>in</strong>c,0) concept-checks, s<strong>in</strong>ce the required concept<br />
map has been def<strong>in</strong>ed.<br />
While <strong>in</strong> the above example, requirements on the twice function were all given<br />
<strong>in</strong> the requires clause, concepts can be also written “<strong>in</strong>l<strong>in</strong>e.” Thus, the Function<br />
requirement from could be also written as:<br />
template<br />
We use the <strong>in</strong>l<strong>in</strong>e notation frequently as it signifies the “types of types” role of concepts.<br />
As concepts are an experimental feature they are not supported by common compilers.<br />
To make the <strong>C++</strong> code compilable on st<strong>and</strong>ard compilers we use traits (Myers,<br />
1995) to simulate concepts. Traits are template classes which provide b<strong>in</strong>d<strong>in</strong>gs for associated<br />
entities by specialisations for particular types, <strong>with</strong>out be<strong>in</strong>g able to check the<br />
type correctness of templates.<br />
The <strong>C++</strong> code <strong>in</strong> this paper is tested <strong>with</strong> the gcc compiler 1 , version 4.3, <strong>and</strong> the<br />
1 http://gcc.gnu.org/<br />
7
concept code is partly tested <strong>with</strong> the ConceptGCC compiler 2 (version alpha 7). In<br />
<strong>C++</strong>, we name concepts <strong>in</strong> CamelCase, <strong>and</strong> for class names we use Camel_Case <strong>with</strong><br />
underscores. Furthermore, <strong>in</strong> the <strong>C++</strong> code we usually omit unnecessary details such as<br />
const qualifiers or reference (&) type modifiers—while these are important for performance<br />
they do not contribute to the exposition. F<strong>in</strong>ally, <strong>in</strong> template parameter lists, the<br />
keywords class <strong>and</strong> typename are freely exchangeable—the variations <strong>in</strong> the paper are<br />
motivated by space constra<strong>in</strong>ts.<br />
1.1.4. <strong>Haskell</strong> <strong>with</strong> concepts<br />
<strong>Concepts</strong> are implemented <strong>in</strong> <strong>Haskell</strong> by the means of type classes (Wadler <strong>and</strong><br />
Blott, 1989). Models of concepts are declared by the <strong>in</strong>stance declaration keyword,<br />
constra<strong>in</strong><strong>in</strong>g an algorithm <strong>with</strong> concept requirements is done <strong>with</strong> the => declaration.<br />
We make frequent use of the concepts Monad <strong>with</strong> members functions (>>=) (pronounced<br />
“b<strong>in</strong>d”) <strong>and</strong> return <strong>and</strong> the Functor concept <strong>with</strong> the member function fmap.<br />
1 class Functor f where<br />
2 fmap :: (a -> b) -> f a -> f b<br />
3<br />
4 class Monad m where<br />
5 (>>=) :: m a -> (a -> m b) -> m b<br />
6 return :: a -> m a<br />
Note that the parameters f <strong>and</strong> m are of k<strong>in</strong>d * ->*, so these concepts (type classes)<br />
constra<strong>in</strong> type constructors, not types. Type classes <strong>with</strong> parameter of other k<strong>in</strong>d than<br />
* are sometimes called constructor classes (Jones, 1993).<br />
The list type constructor [] is a model of both the Functor <strong>and</strong> the Monad concept:<br />
1 <strong>in</strong>stance Functor [] where<br />
2 fmap = map<br />
3<br />
4 <strong>in</strong>stance Monad [] where<br />
5 xs >>= f = concat (map f xs)<br />
6 return x = [x]<br />
Over the years <strong>Haskell</strong> has acquired a number of extensions (for multiple parameters,<br />
associated types, equality constra<strong>in</strong>ts, etc.) to the basic idea of type classes <strong>and</strong> <strong>in</strong><br />
Sect. 4 we use quite a few of those extensions to port the <strong>C++</strong> conceptual framework<br />
for monadic dynamical systems “back to <strong>Haskell</strong>”.<br />
2. Vulnerability Modell<strong>in</strong>g<br />
In the past decade, the concept of “vulnerability” has played an important role <strong>in</strong><br />
fields such as climate change, food security, <strong>and</strong> natural hazard studies. Vulnerability<br />
studies have been useful <strong>in</strong> alert<strong>in</strong>g policymakers to the possibility of precarious<br />
situations <strong>in</strong> the future.<br />
2 http://www.generic-programm<strong>in</strong>g.org/software/ConceptGCC/<br />
8
However, def<strong>in</strong>itions of vulnerability vary: there seem to be almost as many def<strong>in</strong>itions<br />
of vulnerability as case studies conducted. Wolf et al. (2008), for <strong>in</strong>stance,<br />
analyse the usage of 20 def<strong>in</strong>itions of vulnerability. An allegory frequently used to<br />
describe the term<strong>in</strong>ology is the Babylonian confusion, <strong>and</strong> the need for a common underst<strong>and</strong><strong>in</strong>g<br />
has repeatedly been expressed <strong>in</strong> the literature (Brooks, 2003; Janssen <strong>and</strong><br />
Ostrom, 2006).<br />
While def<strong>in</strong>itions of vulnerability are usually imprecise, Ionescu (2009) proposes<br />
a mathematically def<strong>in</strong>ed framework that underlies the def<strong>in</strong>itions <strong>and</strong> the usage of the<br />
term vulnerability. Ionescu’s framework applies to those studies that “project future<br />
conditions” by us<strong>in</strong>g computational tools <strong>and</strong> that can thus be designated as computational<br />
vulnerability assessment. This common framework for vulnerability assessment<br />
consists of three primitive concepts: an entity (which is subject to possible future<br />
harm), possible future evolutions (of the entity), <strong>and</strong> harm. Next, we briefly summarise<br />
Ionescu’s development. First, we discuss the primitive concepts <strong>and</strong>, then, their extension<br />
to monadic dynamical systems.<br />
2.1. A Simple Mathematical Model of Vulnerability<br />
An entity, its current situation, <strong>and</strong> its environment are described by a state. In<br />
vulnerability computations, the current state of an entity is only a start<strong>in</strong>g po<strong>in</strong>t; it is the<br />
evolution of the state over time that is the ma<strong>in</strong> focus of <strong>in</strong>terest. A s<strong>in</strong>gle evolution path<br />
of an entity is called a trajectory. In a first, simple vulnerability model, the evolution<br />
of an entity is computed <strong>in</strong> a s<strong>in</strong>gle step:<br />
1 possible :: State -> F Evolution<br />
The possible function maps a state <strong>in</strong>to an F-structure of future evolutions. Two<br />
types <strong>and</strong> one type constructor are <strong>in</strong>volved: State is the type of the state of an entity,<br />
Evolution is the type of the evolution of an entity, <strong>and</strong> F is the type constructor<br />
represent<strong>in</strong>g the structure of evolutions (e.g., a set). In this simple model we take<br />
Evolution = [State]: an evolution is a f<strong>in</strong>ite sequence of the states that an entity<br />
successively assumes over time. This notion is sufficient, as most vulnerability assessments<br />
are made for a given horizon, which is expressible as a f<strong>in</strong>ite evolution.<br />
The constructor F is a functor (see Sect. 1.1) that describes the nature of the future<br />
computation. For example, if the future of an entity is determ<strong>in</strong>istic, one would<br />
have F = Id, the identity functor, giv<strong>in</strong>g a s<strong>in</strong>gle evolution. Sometimes, a more sophisticated<br />
model may be necessary. For <strong>in</strong>stance, a stochastic model might be used,<br />
which computes probability distributions over trajectories; the stochastic functor <strong>in</strong>troduced<br />
<strong>in</strong> Sect. 1.1 captures such situations (F = SimpleProb). Some other models<br />
might produce just lists of trajectories, <strong>with</strong>out assign<strong>in</strong>g a specific probability to each<br />
possibility. For these models, the trajectories are enclosed <strong>in</strong> the list functor (F = []).<br />
The second <strong>in</strong>gredient of a vulnerability computation is a harm judgement function:<br />
1 harm :: Evolution -> Harm<br />
The harm function maps evolutions <strong>in</strong>to values of type Harm, which describes the nature<br />
of the harm assessment. One of the simplest harm assessments is a threshold measurement.<br />
Examples of thresholds that can be crossed <strong>in</strong>clude temperature that grows too<br />
9
high or a budget that is too low. Correspond<strong>in</strong>gly, threshold harm measurement judges<br />
two possibilities, namely “yes, there is harm for this evolution” or “no, there isn’t any<br />
harm when the entity evolves <strong>in</strong> this way.” In such cases, harm is simply a boolean<br />
value (Harm = Bool). In other models, the harm value for each trajectory may be measured<br />
as a real value (Harm = R). A more sophisticated model might measure multiple<br />
dimensions of harm, all expressed as real values, which would lead to Harm = R N .<br />
The harm function measures the harm of a s<strong>in</strong>gle evolution, but a model produces<br />
an F-structure of evolutions, given some implementation of the function possible. The<br />
harm function must then be mapped to the evolutions, us<strong>in</strong>g the fmap function of the<br />
functor F (see Sect. 1.1). A measure function takes the result<strong>in</strong>g F-structure of harm<br />
values <strong>and</strong> summarises them <strong>in</strong>to an overall measurement:<br />
1 measure :: F Harm -> V<br />
The codoma<strong>in</strong> of the measure function could be, for example, the real numbers (to get<br />
the result as a s<strong>in</strong>gle number, a way of expression policymakers prefer) or a multidimensional<br />
space (to express various dimensions of vulnerability <strong>in</strong>stead of collaps<strong>in</strong>g<br />
it <strong>in</strong>to a s<strong>in</strong>gle number). Common examples for the measure function are measure<br />
= maximum <strong>in</strong> the case of F = [] <strong>and</strong> Harm = Bool, or measure = expectation <strong>in</strong> the<br />
case of F = SimpleProb <strong>and</strong> Harm = R.<br />
Comb<strong>in</strong><strong>in</strong>g these three functions gives the vulnerability computation:<br />
1 vulnerability :: State -> V<br />
2 vulnerability = measure . fmap harm . possible<br />
This computation captures the idea beh<strong>in</strong>d many vulnerability def<strong>in</strong>itions: we measure<br />
the harm that might be possible. The follow<strong>in</strong>g example illustrates the use of the<br />
vulnerability computation framework:<br />
1 type Economy_State = (Double, Double, Double, ...)<br />
2 -- GDP, GDP-growth, Unemployment Rate, <strong>and</strong> so on ...<br />
3 type Economy_Evolution = [Economy_State]<br />
4<br />
5 possible_economy :: Economy_State -> [ Economy_Evolution ]<br />
6 possible_economy x = -- ... implement a model of an economy here<br />
7<br />
8 economic_harm :: Economy_Evolution -> Double<br />
9 economic_harm ec_ev = -- ... return -(biggest GDP-change)<br />
10<br />
11 economic_vulnerability :: Economy_State -> Double<br />
12 economic_vulnerability = maximum . fmap economic_harm . possible_economy<br />
The implementation of the economy evolution function is unspecified, but the type<br />
<strong>in</strong>dicates that it is performed non-determ<strong>in</strong>istically. Harm is def<strong>in</strong>ed as the greatest<br />
decrease <strong>in</strong> Gross Domestic Product (GDP) over a trajectory; the harm function returns<br />
zero if the GDP is always <strong>in</strong>creas<strong>in</strong>g. In the f<strong>in</strong>al vulnerability computation, the<br />
maximum function is used as measure, def<strong>in</strong><strong>in</strong>g vulnerability as the greatest economic<br />
loss over all possible evolutions of the economy from a given state.<br />
10
2.2. Vulnerability measures<br />
An important result of this analysis, go<strong>in</strong>g beyond the implementation of software<br />
components, is the <strong>in</strong>creased underst<strong>and</strong><strong>in</strong>g of vulnerability. This is often the case <strong>with</strong><br />
develop<strong>in</strong>g a Doma<strong>in</strong> Specific Language (DSL): the activity leads to a deeper underst<strong>and</strong><strong>in</strong>g<br />
of the doma<strong>in</strong>, not just for the computer scientist, but even for the doma<strong>in</strong><br />
expert. We give here a couple of examples.<br />
We were able to formulate precisely the natural condition of consistency between<br />
the impact evaluations <strong>and</strong> the vulnerability measure: if the harm <strong>in</strong> the structure <strong>in</strong>creases,<br />
then the vulnerability measure should not decrease. This can be formalised<br />
as follows: for any function f :: Harm -> Harm <strong>with</strong> h V <strong>and</strong> m2 :: F2 Harm -> V are<br />
said to be compatible <strong>with</strong> respect to tau if, for all hs1, hs2 :: F1 Harm we have<br />
that m1 hs1
2.3. <strong>Monadic</strong> <strong>Systems</strong> <strong>and</strong> Vulnerability<br />
The simple model of vulnerability presented <strong>in</strong> the previous section has two ma<strong>in</strong><br />
disadvantages. First, it is not very generic: as shown <strong>in</strong> the economy example we have<br />
to write a new function for every vulnerability computation. This can easily be fixed by<br />
mak<strong>in</strong>g possible, harm <strong>and</strong> measure <strong>in</strong>puts to the vulnerability computation. Second,<br />
the model is <strong>in</strong>flexible: the evolution function of the simple model only consumes the<br />
<strong>in</strong>itial state of a system as the <strong>in</strong>put. In practise, however, an evolution function often<br />
has more <strong>in</strong>puts. In particular, an evolution may depend on auxiliary control arguments<br />
that are not part of the <strong>in</strong>itial state of a system.<br />
Ionescu (2009) explores possible structures which might provide the required flexibility.<br />
On the one h<strong>and</strong> the multitude of systems which might be <strong>in</strong>volved has to be<br />
represented, on the other h<strong>and</strong> we want an easy way of comput<strong>in</strong>g iterations. It turns<br />
out that a functorial structure on the possible evolutions is not suitable for the trajectory<br />
computations <strong>and</strong> that the use of a monad <strong>in</strong>stead of a functor gives the possibility<br />
to iterate a system. Therefore, the notion of a monadic dynamical system (MDS) was<br />
<strong>in</strong>troduced. In contrast to the possible function, trajectories of a model def<strong>in</strong>ed by<br />
an MDS can be computed <strong>in</strong> multiple separate steps. For example, a trajectory of an<br />
MDS can be computed up to a certa<strong>in</strong> po<strong>in</strong>t, the result archived, <strong>and</strong> the computation<br />
cont<strong>in</strong>ued later <strong>with</strong> this <strong>in</strong>termediate result as a start<strong>in</strong>g po<strong>in</strong>t.<br />
An MDS is a mapp<strong>in</strong>g <strong>with</strong> the signature t -> (x -> m x), where m is a monad<br />
(see Sect. 1.1). An MDS takes a value of type t (e.g., t = Nat) to a (monadic) transition<br />
function of type x -> m x. Every MDS must fulfil some further conditions; for<br />
<strong>in</strong>stance, the type t has to form a monoid structure (<strong>with</strong> a zero z <strong>and</strong> an operation<br />
(+.)) <strong>and</strong> the MDS must preserve that structure (must be a monoid morphism). More<br />
precisely, the follow<strong>in</strong>g two laws (expressed as predicates) have to be satisfied (where<br />
(=.=) is po<strong>in</strong>twise equality for functions):<br />
1 sys_law_zero sys = sys z =.= return<br />
2 sys_law_plus sys t1 t2 = sys (t1 +. t2) =.= (sys t2 [Int]<br />
2 my_discrete_trans x = [x-1, x+1]<br />
We can construct an MDS from my_discrete_trans us<strong>in</strong>g discrete_sys:<br />
1 type Nat = Int<br />
2 discrete_sys :: (Monad m) => (x -> m x) -> (Nat -> x -> m x)<br />
3 discrete_sys f n = mcompose (replicate n f)<br />
Not all transitions of <strong>in</strong>terest are that simple. Often, a transition function does<br />
not only map a state <strong>in</strong>to an M-structure of states, but also takes an additional control<br />
parameter. This parameter describes some external <strong>in</strong>put which is not a part of the<br />
12
state. Such a function describes a family of transition functions, one for each control<br />
<strong>in</strong>put. Consider the follow<strong>in</strong>g example:<br />
1 type MyControl = Double<br />
2 type MyState = Double<br />
3 my_<strong>in</strong>put_trans :: MyControl -> (MyState -> SimpleProb MyState)<br />
4 my_<strong>in</strong>put_trans delta x = SP [(x + delta, 0.75),<br />
5 (x - delta, 0.25)]<br />
Here, every <strong>in</strong>put delta gives a different transition function. The function itself is not<br />
an MDS (because it fails to satisfy the MDS laws). But it can be used to construct a<br />
monadic system by us<strong>in</strong>g the follow<strong>in</strong>g constructor:<br />
1 <strong>in</strong>put_system :: (Monad m) => (i -> x -> m x) -> ([i] -> x -> m x)<br />
2 <strong>in</strong>put_system trans = mcompose . map trans<br />
Furthermore, given an MDS, two iteration functions can be def<strong>in</strong>ed: the macro<br />
trajectory function, macro_trj, computes the evolution of an M-structure of states, <strong>and</strong><br />
the micro trajectory, micro_trj, computes the M-structure of evolutions (sequences of<br />
states). Both computations start <strong>with</strong> a sequence of <strong>in</strong>puts of type i <strong>and</strong> an <strong>in</strong>itial state.<br />
The macro trajectory describes all possible states at each step of the computation, but<br />
does not connect them:<br />
1 macro_trj :: (Monad m) => (i -> (x -> m x)) -> [i] -> x -> [m x]<br />
2 macro_trj sys ts x = scanr (\i mx -> mx >>= sys i) (return x) ts<br />
The micro trajectory records the s<strong>in</strong>gle evolution paths <strong>in</strong>clud<strong>in</strong>g all <strong>in</strong>termediate states:<br />
1 micro_trj :: (Monad m) => (i -> (x -> m x)) -> [i] -> x -> m [x]<br />
2 micro_trj sys is x = mcompose (map (addHist . sys) is) [x]<br />
3<br />
4 addHist :: (Monad f) => (x -> f x) -> [x] -> f [x]<br />
5 addHist g (x : xs) = liftM (:(x : xs)) (g x)<br />
Comput<strong>in</strong>g the trajectories for the MDS constructed out of my_discrete_trans from<br />
the <strong>in</strong>itial state myx = 0 <strong>and</strong> the <strong>in</strong>put sequence myts = [1,1,1] yields:<br />
1 macro_trj (discrete_sys my_discrete_trans) myts myx ==<br />
2 [ [-3,-1,-1,1,-1,1,1,3],<br />
3 [-2,0,0,2],<br />
4 [-1,1],<br />
5 [0]]<br />
6<br />
7 micro_trj (discrete_sys my_discrete_trans) myts myx ==<br />
8 [ [-3,-2,-1, 0], [-1,-2,-1, 0], [-1, 0,-1, 0], [ 1, 0,-1, 0],<br />
9 [-1, 0, 1, 0], [ 1, 0, 1, 0], [ 1, 2, 1, 0], [ 3, 2, 1, 0]<br />
10 ]<br />
The example clarifies the nature of the two trajectory computations: The macro trajectory<br />
provides the <strong>in</strong>formation that the state of this system is 0 at the beg<strong>in</strong>n<strong>in</strong>g. After<br />
one step the state is either -1 or 1, after two steps it can be <strong>in</strong> state -2, 0 or 2 <strong>and</strong> so<br />
on. The micro trajectory function returns all the <strong>in</strong>dividual trajectories the system can<br />
take, from [-3,-2-1,0], where we always take the -1 path, to [3,2,1,0]. Macro <strong>and</strong><br />
micro trajectories are, as shown by Ionescu (2009), related by:<br />
13
1 fmap (!!n) (micro_trj sys ts x) == (macro_trj sys ts x !! n)<br />
It should be noted that while the trajectory computations work for any monadic coalgebra<br />
<strong>with</strong> <strong>in</strong>put, these laws are only valid for monadic dynamical systems (Ionescu,<br />
2009). Note furthermore, that the computed states are prepended to the list, lead<strong>in</strong>g to<br />
the un<strong>in</strong>tuitive order<strong>in</strong>g of states <strong>with</strong> the f<strong>in</strong>al state at the head of the list. The <strong>in</strong>put of<br />
myts are processed <strong>in</strong> the same order: start<strong>in</strong>g from the end of the list <strong>and</strong> proceed<strong>in</strong>g<br />
to the first element.<br />
Many computational models used <strong>in</strong> the climate change community already implicitly<br />
implement the structure of an MDS. For <strong>in</strong>stance, the climate model CLIMBER<br />
(Petoukhov et al., 2000) has an <strong>in</strong>ternal state which represents the current configuration<br />
of certa<strong>in</strong> physical parameters. In addition, CLIMBER takes as an <strong>in</strong>put the concentration<br />
of greenhouse gases. The CLIMBER model can be described as an MDS built from<br />
a family of transition functions <strong>with</strong> signature climber :: GHG -> (Climber_st -><br />
F Climber_st), where GHG is the type of values represent<strong>in</strong>g concentration of greenhouse<br />
gases, <strong>and</strong> F = Id is the identity monad, s<strong>in</strong>ce CLIMBER is determ<strong>in</strong>istic.<br />
To tie back to vulnerability assessment, the micro_trj computation for an MDS<br />
fits the signature of the possible function <strong>in</strong> a vulnerability computation. Thus, the<br />
possible can be computed as the structure of micro-trajectories of an MDS. Tak<strong>in</strong>g<br />
this <strong>in</strong>to account we can compute vulnerability as:<br />
1 vulnerability’ :: (Functor m, Monad m) =><br />
2 (i -> x -> m x) -> ([x] -> h) -><br />
3 (m h -> v) -> [i] -> x -> v<br />
4 vulnerability’ sys harm measure ts = measure . fmap harm . micro_trj sys ts<br />
Us<strong>in</strong>g the above def<strong>in</strong>itions, the examples of the possible functions from the previous<br />
section, <strong>with</strong> F = Id, F = [], or F = SimpleProb as the result<strong>in</strong>g structures, can all be<br />
easily translated to an MDS, s<strong>in</strong>ce all these functors are also monads.<br />
2.4. Comb<strong>in</strong><strong>in</strong>g monadic dynamical systems<br />
One monadic system is rarely used alone, at least <strong>in</strong> vulnerability assessment. It<br />
is, <strong>in</strong> fact, a common task to build a model of a complex system, such as the climate<br />
system, from build<strong>in</strong>g blocks: a model of the atmosphere, a model of the ocean, one<br />
for the ice-sheets at the poles, <strong>and</strong> so on. There are problems that are characteristic for<br />
the type of modell<strong>in</strong>g needed <strong>in</strong> vulnerability studies. In particular the build<strong>in</strong>g blocks<br />
are often represented <strong>in</strong> very different ways: physical systems might be described by<br />
determ<strong>in</strong>istic or stochastic systems, while the social systems are usually described as<br />
non-determ<strong>in</strong>istic or fuzzy. Even if all the systems operate on the same time scale,<br />
even if the geographical resolution is identical <strong>and</strong> all shared variables have uniform<br />
semantics, it is still not clear how to compute the trajectory of a comb<strong>in</strong>ation of, say,<br />
determ<strong>in</strong>istic <strong>and</strong> non-determ<strong>in</strong>istic systems.<br />
Unfortunately, there is no unique way of comb<strong>in</strong><strong>in</strong>g monads to yield monads (K<strong>in</strong>g<br />
<strong>and</strong> Wadler, 1992). The same two monads may be comb<strong>in</strong>ed differently, yield<strong>in</strong>g different<br />
results. Accord<strong>in</strong>gly, we present those comb<strong>in</strong>ations of systems which are most<br />
likely to be useful <strong>in</strong> the practice of computational vulnerability assessment.<br />
14
The simplest way of comb<strong>in</strong><strong>in</strong>g two systems is to put them <strong>in</strong> parallel. The trajectories<br />
of the two systems are computed <strong>in</strong>dependently, <strong>and</strong> are comb<strong>in</strong>ed by tupl<strong>in</strong>g.<br />
Thus, given two systems sys1 :: t1 -> x -> m x <strong>and</strong> sys2 :: t2 -> y -><br />
n y, putt<strong>in</strong>g them <strong>in</strong> parallel results <strong>in</strong> the system syspar (sys1, sys2) :: (t1, t2)<br />
-> (x, y) -> (m x, n y). It is trivial to check that syspar (sys1, sys2) is a monoid<br />
morphism (given that sys1 <strong>and</strong> sys2 are monoid morphisms).<br />
However, syspar (sys1, sys2) cannot be made a monadic dynamical system <strong>in</strong><br />
<strong>Haskell</strong>, because of the fact that there is no possibility to declare (M, N) to be a monad<br />
as the notion (M, N) does not even type check. In order to circumvent this problem<br />
we provide a technical workaround which starts <strong>with</strong> def<strong>in</strong><strong>in</strong>g the “pair<strong>in</strong>g” of two<br />
monads:<br />
1 newtype PairM m n a = PM (m a, n a)<br />
2 unwrapPM :: PairM m n a -> (m a, n a)<br />
3 unwrapPM (PM x) = x<br />
4<br />
5 <strong>in</strong>stance (Monad m, Monad n) => Monad (PairM m n) where<br />
6 return x = PM (return x , return x )<br />
7 (PM (mx, nx)) >>= f = PM (mx0, nx0)<br />
8 where<br />
9 mx0 = mx >>= (fst . unwrapPM . f )<br />
10 nx0 = nx >>= (snd . unwrapPM . f )<br />
11<br />
12 pr :: Functor f => (f a, b) -> f (a, b)<br />
13 pr (fa, b) = fmap (\a -> (a, b)) fa<br />
14<br />
15 pl :: Functor f => (b, f a) -> f (b, a)<br />
16 pl (b, fa) = fmap (\a -> (b, a)) fa<br />
17<br />
18 syspar :: (Functor m, Functor n) =><br />
19 (t1 -> x -> m x , t2 -> y -> n y) -><br />
20 (t1, t2) -> ((x, y) -> PairM m n (x, y))<br />
21 syspar (sys1, sys2) (t1, t2) (x, y) = PM (pr (sys1 t1 x, y),<br />
22 pl ( x, sys2 t2 y))<br />
Even if the def<strong>in</strong>ition of syspar only requires the functoriality of m <strong>and</strong> n, further conditions<br />
are needed for syspar (sys1, sys2) to also be a monoid morphism, therefore<br />
a monadic system. (More precisely, m <strong>and</strong> n need to be monads <strong>and</strong> sys1 <strong>and</strong> sys2<br />
monoid morphisms.)<br />
System comb<strong>in</strong>ation becomes more complicated when the <strong>in</strong>volved systems <strong>in</strong>teract<br />
(someth<strong>in</strong>g they cannot do when comb<strong>in</strong>ed <strong>in</strong> parallel). In the follow<strong>in</strong>g we only<br />
consider <strong>in</strong>teraction through shared state: the two systems are assumed to have the<br />
same state space X, although possibly different monoids <strong>and</strong> monads. This represents<br />
the follow<strong>in</strong>g situation: an <strong>in</strong>itial state (element of X) is modified by the first system<br />
accord<strong>in</strong>g to an <strong>in</strong>put from its own monoid, the result<strong>in</strong>g macro-state is then modified<br />
by the second system accord<strong>in</strong>g to an <strong>in</strong>put from its monoid, <strong>and</strong> so on. If both systems<br />
have the same monad, that is sys1 :: t1 -> x -> m x <strong>and</strong> sys2 :: t2 -> x -><br />
m x, one could expect the serial comb<strong>in</strong>ation to be def<strong>in</strong>ed as: comb (sys1, sys2)<br />
(t1, t2) = (sys2 t2)
Ionescu (2009) for explanation). Rather, we can def<strong>in</strong>e a system comb<strong>in</strong>ation sysser<br />
which uses pairs (t1, t2) as <strong>in</strong>puts:<br />
1 sysser :: (Monad m) => (t1 -> x -> m x,<br />
2 t2 -> x -> m x) -><br />
3 [(t1, t2)] -> x -> m x<br />
4 sysser (sys1, sys2) = <strong>in</strong>put_system f<br />
5 where f (t1, t2) = sys2 t2 (t1 -> x -> Id x,<br />
2 t2 -> x -> m x) -><br />
3 [(t1, t2)]-> x -> m x<br />
4 detserl (detsys, sys) = sysser (embedMDS detsys, sys)<br />
5<br />
6 detserr :: (Monad m) => (t1 -> x -> m x,<br />
7 t2 -> x -> Id x) -><br />
8 [(t1, t2)]-> x -> m x<br />
9 detserr (sys, detsys) = sysser (sys, embedMDS detsys)<br />
10<br />
11 embedMDS :: (Monad m) => (t -> a1 -> Id a) -> t -> a1 -> m a<br />
12 embedMDS detsys t = return . unwrapId . detsys t<br />
If there is no determ<strong>in</strong>istic system <strong>in</strong>volved, serial comb<strong>in</strong>ation becomes more difficult.<br />
This case is beyond the scope of this paper, we refer to Ionescu (2009) for discussion.<br />
3. Vulnerability Modell<strong>in</strong>g <strong>in</strong> <strong>C++</strong> <strong>with</strong> <strong>Concepts</strong><br />
In the previous section, we used <strong>Haskell</strong> to describe monadic systems <strong>and</strong> vulnerability<br />
assessment at high level, more <strong>in</strong> the mathematical specification style than as a<br />
practical computational library. Thanks to its laz<strong>in</strong>ess <strong>and</strong> its clean notation, <strong>Haskell</strong><br />
serves well as a modell<strong>in</strong>g <strong>and</strong> prototyp<strong>in</strong>g language that enables one to write operational<br />
def<strong>in</strong>itions that can be executed.<br />
However, an executable specification such as the one we have given <strong>in</strong> the previous<br />
section is not practical <strong>in</strong> real-life scientific programm<strong>in</strong>g. High-performance<br />
comput<strong>in</strong>g is usually performed <strong>in</strong> very specific <strong>and</strong> complex environments, <strong>and</strong> often<br />
there are many exist<strong>in</strong>g libraries <strong>and</strong> code bases that must be <strong>in</strong>tegrated. In this section<br />
we present a <strong>C++</strong> library for monadic dynamical systems that addresses the shortcom<strong>in</strong>gs<br />
of the high-level <strong>Haskell</strong> description while ma<strong>in</strong>ta<strong>in</strong><strong>in</strong>g much of the description’s<br />
clarity <strong>and</strong> structure. We choose <strong>C++</strong> because of its support of high-level generic programm<strong>in</strong>g,<br />
the ease <strong>with</strong> which exist<strong>in</strong>g components can be <strong>in</strong>tegrated, <strong>and</strong> because<br />
<strong>C++</strong> is well supported on high-performance platforms.<br />
Our choice of <strong>C++</strong> is not a crucial decision. By express<strong>in</strong>g the high-level structure of<br />
functional constructs <strong>in</strong> a generic manner by specify<strong>in</strong>g their requirements as concepts,<br />
16
our library is implementable <strong>in</strong> every language that provides support for generic programm<strong>in</strong>g<br />
<strong>with</strong> concepts. While we rely on the <strong>C++</strong> concepts (discussed <strong>in</strong> Sect. 1.1.3)<br />
to capture the notions of the doma<strong>in</strong>, a recent study by Garcia et al. shows that there are<br />
other languages <strong>with</strong> an appropriate generic programm<strong>in</strong>g support. In section Sect. 4<br />
we sketch how a similar concept-based library can be constructed <strong>in</strong> <strong>Haskell</strong>.<br />
Our methodology is to transform the <strong>Haskell</strong> description <strong>in</strong> a pr<strong>in</strong>cipled way to a<br />
correspond<strong>in</strong>g conceptual specification, <strong>and</strong> implement<strong>in</strong>g a <strong>C++</strong> framework based on<br />
that specification. In the nutshell, we reflect the <strong>Haskell</strong> types from the previous section<br />
us<strong>in</strong>g concepts so that, for example, function types <strong>and</strong> type constructors are expressed<br />
by concepts. This allows our library to freely glue exist<strong>in</strong>g code bases by plugg<strong>in</strong>g<br />
them <strong>in</strong>to well def<strong>in</strong>ed “slots” given by concepts. The algorithms <strong>and</strong> comb<strong>in</strong>ators are<br />
expressed as generic functions <strong>and</strong> types, respectively. We present our methodology <strong>in</strong><br />
more detail <strong>in</strong> the rema<strong>in</strong>der of this section, as we describe the particular elements of<br />
our library.<br />
The approach is split <strong>in</strong>to two libraries. The first one, discussed <strong>in</strong> Sect. 3.1, is the<br />
encod<strong>in</strong>g of basic functional-programm<strong>in</strong>g types <strong>and</strong> features. As such, this library is<br />
useful, or even strictly necessary, for any future development styled after our work. The<br />
second library (Sect. 3.2), build<strong>in</strong>g upon the first one, <strong>in</strong>troduces the notions necessary<br />
for monadic dynamical systems.<br />
3.1. A Functional <strong>Concepts</strong> Library<br />
The <strong>Haskell</strong> description of monadic dynamical systems, as shown <strong>in</strong> Sect. 2, uses<br />
the features of <strong>Haskell</strong> that make it a language so well suited for computable specifications.<br />
In particular, functions <strong>and</strong> categorial constructs such as monads or functors can<br />
be easily represented <strong>in</strong> the type system us<strong>in</strong>g first-class function types <strong>and</strong> type constructors.<br />
In this section, we encode these high-level features <strong>in</strong> a generic manner that<br />
makes it possible to reimplement them <strong>in</strong> non-functional languages <strong>and</strong> bridge them<br />
<strong>with</strong> exist<strong>in</strong>g code bases.<br />
We beg<strong>in</strong> <strong>with</strong> the most basic concept underly<strong>in</strong>g the specification of vulnerability:<br />
functions. In the <strong>Haskell</strong> description from Sect. 2, we use the built-<strong>in</strong> function type<br />
(->). This makes perfect sense <strong>in</strong> the sett<strong>in</strong>g where clarity is of topmost importance. In<br />
general, however, there are many programm<strong>in</strong>g languages that do not provide a built-<strong>in</strong><br />
function type. Function types are available <strong>in</strong> <strong>C++</strong>, but they are only useful for form<strong>in</strong>g<br />
function po<strong>in</strong>ters <strong>and</strong> meta-programm<strong>in</strong>g. As discussed by L<strong>in</strong>cke <strong>and</strong> Schupp (2009)<br />
there are multiple ways of implement<strong>in</strong>g mathematical functions <strong>in</strong> <strong>C++</strong>. L<strong>in</strong>cke <strong>and</strong><br />
Schupp consider mostly the efficiency of different implementations, but <strong>in</strong>tegration of<br />
legacy code is equally important, at least <strong>in</strong> our sett<strong>in</strong>g. A scientist wish<strong>in</strong>g to employ<br />
our vulnerability library may have an exist<strong>in</strong>g <strong>and</strong> potentially complex platformspecific<br />
implementation of particular functions. Therefore, <strong>in</strong>stead of us<strong>in</strong>g a particular<br />
type, we <strong>in</strong>troduce a Function concept that captures the basic requirements on a type<br />
implement<strong>in</strong>g functions. Every type which models unary functions has to provide the<br />
follow<strong>in</strong>g entities:<br />
• an associated doma<strong>in</strong> type (called Doma<strong>in</strong>1 3 ),<br />
3 We choose the name Doma<strong>in</strong>1 over just Doma<strong>in</strong> for consistency <strong>with</strong> higher-arity function concepts.<br />
17
• an associated codoma<strong>in</strong> type (called Codoma<strong>in</strong>),<br />
• <strong>and</strong> an application operator mapp<strong>in</strong>g elements of the doma<strong>in</strong> <strong>in</strong>to the codoma<strong>in</strong>.<br />
The function concept conta<strong>in</strong><strong>in</strong>g these associated entities is implemented directly:<br />
1 // Fun ~ a -> b<br />
2 concept Function {<br />
3 typename Doma<strong>in</strong>1;<br />
4 typename Codoma<strong>in</strong>;<br />
5<br />
6 Codoma<strong>in</strong> operator () (Fun, Doma<strong>in</strong>1);<br />
7 };<br />
Although the call operator, as written above, takes an object of type Fun as one of<br />
its arguments, the actual syntax of a function call on types modell<strong>in</strong>g the concept is<br />
f(x) where f is of type Fun <strong>and</strong> x is of type Doma<strong>in</strong>1.<br />
In general, crucial doma<strong>in</strong> notions from the <strong>Haskell</strong> description are translated <strong>in</strong>to<br />
concepts, class templates, or generic functions, depend<strong>in</strong>g on their role <strong>in</strong> the library.<br />
For example, our library provides a function composition operator, implemented as<br />
a class template “typed” <strong>with</strong> concepts, that given two functions as <strong>in</strong>put provides a<br />
composed function:<br />
1 // F ~ a -> b, G ~ b -> c<br />
2 template <br />
3 requires<br />
4 std::CopyConstructible, std::CopyConstructible,<br />
5 std::SameType<br />
6 class Composed_Function {<br />
7 public:<br />
8 typedef F::Doma<strong>in</strong>1 Doma<strong>in</strong>1;<br />
9 typedef G::Codoma<strong>in</strong> Codoma<strong>in</strong>;<br />
10<br />
11 // The constructor just stores f <strong>in</strong> my_f <strong>and</strong> g <strong>in</strong> my_g<br />
12 Composed_Function(F f, G g) : my_f(f), my_g(g) {}<br />
13<br />
14 Codoma<strong>in</strong> operator() (Doma<strong>in</strong>1 x) const { return my_g(my_f(x)); }<br />
15 private:<br />
16 F my_f;<br />
17 G my_g;<br />
18 };<br />
The Composed_Function comb<strong>in</strong>ator is implemented as a constra<strong>in</strong>ed class template.<br />
Its constra<strong>in</strong>ts correspond to the <strong>Haskell</strong> type signature (a->b)-> (b->c)-> (a->c)<br />
by stat<strong>in</strong>g that the two type parameters must each be models of the Function concept.<br />
Doma<strong>in</strong>s <strong>and</strong> codoma<strong>in</strong>s of the functions are left unspecified (type variables a, b, <strong>and</strong><br />
c <strong>in</strong> the <strong>Haskell</strong> type), mak<strong>in</strong>g Composed_Function polymorphic <strong>in</strong> the doma<strong>in</strong>s <strong>and</strong><br />
codoma<strong>in</strong>s of the composed functions. There is, however, a constra<strong>in</strong>t that the codoma<strong>in</strong><br />
of the first function must be the same as the doma<strong>in</strong> of the second function (the<br />
SameType requirement), correspond<strong>in</strong>g to reuse of the type variable b <strong>in</strong> the <strong>Haskell</strong><br />
type. The CopyConstructible requirements are a technical necessity <strong>in</strong> <strong>C++</strong>, s<strong>in</strong>ce ob-<br />
18
jects represent<strong>in</strong>g functions are copied <strong>and</strong> stored for later use via the <strong>in</strong>itialisation list 4<br />
<strong>in</strong> the Composed_Function constructor. The result type, (a->c) <strong>in</strong> <strong>Haskell</strong>, is not a part<br />
of the def<strong>in</strong>ition of the Composed_Function comb<strong>in</strong>ator. Instead, the result type must<br />
be provided by a concept map stat<strong>in</strong>g that any Composed_Function object is a function<br />
itself:<br />
1 template<br />
2 // requirements forwarded from Composed_Function<br />
3 concept_map Function {<br />
4 typedef F::Doma<strong>in</strong>1 Doma<strong>in</strong>1;<br />
5 typedef G::Codoma<strong>in</strong> Codoma<strong>in</strong>;<br />
6<br />
7 // the b<strong>in</strong>d<strong>in</strong>g for operator() is implicitly generated by the compiler<br />
8 }<br />
The above concept map states that all <strong>in</strong>stantiations of Composed_Function model the<br />
Function concept. The requirements on the F <strong>and</strong> G template arguments of the concept<br />
map are propagated from the def<strong>in</strong>ition of the Composed_Function comb<strong>in</strong>ator, so that<br />
they do not have to be copied <strong>and</strong> pasted. The associated types of the Function concept<br />
are stated explicitly, while the application operator is matched automatically (by name)<br />
to the appropriate def<strong>in</strong>ition <strong>in</strong> the Composed_Function template. The concept map<br />
just states that Composed_Function is a function, but the correspondence between the<br />
types of parameters <strong>and</strong> the type of the result<strong>in</strong>g composed function is encoded by the<br />
def<strong>in</strong>ition of Composed_Function <strong>and</strong> does not result from the concept map alone.<br />
While, by design, our Function concept is presented <strong>in</strong> <strong>C++</strong>, the methodology of<br />
the translation is, besides technicalities, language-<strong>in</strong>dependent:<br />
• for every generic function we have to provide a new (parameterised) type,<br />
• constra<strong>in</strong>ts are used to capture the <strong>in</strong>tended functional signature of this type,<br />
• if the codoma<strong>in</strong> of the function is itself a function type, we have to also <strong>in</strong>troduce<br />
a new type for the codoma<strong>in</strong> (<strong>and</strong> so on),<br />
• every new type which is <strong>in</strong>tended to model a function has to be declared as a<br />
model of the Function concept.<br />
In a similar manner, our library provides more function-related features. For convenience,<br />
we provide multiple argument function concepts such as Function2, Function3,<br />
<strong>and</strong> so on. In addition to the composition comb<strong>in</strong>ator, we provide function curry<strong>in</strong>g.<br />
Both composition <strong>and</strong> curry<strong>in</strong>g are extended to functions <strong>with</strong> multiple parameters.<br />
All comb<strong>in</strong>ators <strong>in</strong> our library come <strong>with</strong> convenience functions that make apply<strong>in</strong>g<br />
the comb<strong>in</strong>ators easier. For example, a compose function is provided for function composition:<br />
1 template <br />
2 requires<br />
3 std::CopyConstructible, std::CopyConstructible,<br />
4 Initialisation list appears after the colon follow<strong>in</strong>g the constructor.<br />
19
4 std::SameType<br />
5 Composed_Function compose(F f, G g) {<br />
6 Composed_Function ret(f, g);<br />
7 return ret;<br />
8 }<br />
Such a function is easier to apply than directly construct<strong>in</strong>g a Composed_Function<br />
object because <strong>C++</strong> automatically deduces template parameters from function call arguments.<br />
A full list of Function-related operations may be found <strong>in</strong> the library source<br />
code (L<strong>in</strong>cke, 2010).<br />
The description of vulnerability <strong>in</strong> Sect. 2 depended on type constructors to represent<br />
categorial notions such as monads or functors. As before, we do not rely on a<br />
particular type or language construct to represent type constructors, but, <strong>in</strong>stead, we<br />
represent type constructors as concepts so that various implementations of type constructors<br />
can be used.<br />
<strong>C++</strong> does not provide support for first-class type constructors. <strong>Concepts</strong> <strong>with</strong> template<br />
template parameters, that is, template parameters that themselves must be templates,<br />
are the most obvious encod<strong>in</strong>g for type constructors where template parameters<br />
represent type constructors. In practise, however, they are not well supported, <strong>and</strong> are<br />
rarely used by <strong>C++</strong> programmers. Also, such higher-order encod<strong>in</strong>g would force programmers<br />
to represent type constructors us<strong>in</strong>g a specific language mechanism (every<br />
constructor would be a template), a restriction we have specifically set out not to impose.<br />
Accord<strong>in</strong>gly, we represent type constructors (of the <strong>Haskell</strong> k<strong>in</strong>d * ->*) <strong>with</strong> a<br />
ConstructorType concept parametrised by a pla<strong>in</strong> template parameter. The concept<br />
provides three one associated entities: a template that represents type constructor application,<br />
an associated type which represents the type the constructor is applied to,<br />
<strong>and</strong> an associated requirement ensur<strong>in</strong>g the consistency of all the <strong>in</strong>gredients:<br />
1 // T ~ f :: *->*<br />
2 concept ConstructorType {<br />
3 template<br />
4 class Apply;<br />
5<br />
6 typename Inner;<br />
7<br />
8 // enforce a connection between T, Inner <strong>and</strong> Apply<br />
9 requires std::SameType;<br />
10 }<br />
A reader familiar <strong>with</strong> type constructors may be immediately baffled by Inner member<br />
<strong>and</strong> the SameType requirement. We <strong>in</strong>troduced the two to get around limitations of the<br />
<strong>C++</strong> type system. The problem is that, <strong>in</strong> general, application of two different constructor<br />
types may result <strong>in</strong> the same type caus<strong>in</strong>g <strong>in</strong>jectivity issues when pattern match<strong>in</strong>g<br />
on type constructor applications. To avoid <strong>in</strong>jectivity problems, our ConstructorType<br />
concept <strong>in</strong>troduces an artificial requirement that the constructor type tag T actually be<br />
an application of the constructor. The SameType requirement is used to establish a connection<br />
between the the constructor type T, the Apply operation, <strong>and</strong> the Inner type.<br />
If the constructor type T is applied to Inner, the result has to be T. Therefore it is not<br />
possible to declare an arbitrary type to be a type constructor. Our <strong>Haskell</strong> version of<br />
20
the ConstructorType concept <strong>in</strong> Sect. 4 is more ideal, rely<strong>in</strong>g on the feature of associated<br />
data types to prevent <strong>in</strong>jectivity errors. A similar technique could be used <strong>in</strong> <strong>C++</strong>,<br />
but s<strong>in</strong>ce there is no feature correspond<strong>in</strong>g directly to associated data types, it would<br />
have to be encoded severely complicat<strong>in</strong>g our library. We believe that <strong>in</strong> connection<br />
<strong>with</strong> template concept maps, our “trick” works out well. For <strong>in</strong>stance, the std::vector<br />
template from the STL is a type constructor:<br />
1 template<br />
2 concept_map ConstructorType {<br />
3 template<br />
4 us<strong>in</strong>g Apply = std::vector;<br />
5<br />
6 typedef T Inner;<br />
7 }<br />
The concept map states that any <strong>in</strong>stantiation of the std::vector template has an associated<br />
type constructor application, <strong>and</strong> it provides the application argument Inner<br />
for pattern match<strong>in</strong>g on particular applications.<br />
Furthermore, we provide a SameTypeConstructor concept that models equivalence<br />
between constructors similarly to how std::SameType concept models equivalence between<br />
types. In addition, as for functions, we provide concepts for type constructors of<br />
different arities.<br />
Us<strong>in</strong>g these simple concepts, we model more complex concepts. The Functor concept<br />
ref<strong>in</strong>es the notion of a type constructor. In <strong>Haskell</strong>, a functor is a type constructor<br />
<strong>with</strong> one additional (polymorphic) operation called fmap:<br />
1 class Functor f :: *->* where<br />
2 fmap :: (a -> b) -> f a -> f b<br />
Us<strong>in</strong>g the ConstructorType concept, we represent functors as follows:<br />
1 // F is a ConstructorType that is a Functor<br />
2 concept Functor : ConstructorType {<br />
3 template<br />
4 F::Apply fmap(Fun, F::Apply);<br />
5 }<br />
We first require that a functor type F be a type constructor by ref<strong>in</strong><strong>in</strong>g the concept<br />
ConstructorType, thus mak<strong>in</strong>g the Functor correspond to a <strong>Haskell</strong> type constructor<br />
class. Then, fmap is provided as an associated member, just as <strong>in</strong> <strong>Haskell</strong>, us<strong>in</strong>g the<br />
type constructor Apply template.<br />
Models for the Functor concept are provided by def<strong>in</strong><strong>in</strong>g the fmap function, as, for<br />
<strong>in</strong>stance, for the std::vector (tak<strong>in</strong>g <strong>in</strong>to account the previously def<strong>in</strong>ed concept map<br />
for the ConstructorType concept):<br />
1 template<br />
2 concept_map Functor {<br />
3 template<br />
4 ConstructorType::Apply<br />
5 fmap(Fun f, ConstructorType::Apply fx) {<br />
6 ConstructorType::Apply ret(fx.size());<br />
7 for (unsigned <strong>in</strong>t i=0; i
8 ret[i] = f(fx[i]);<br />
9 return ret;<br />
10 }<br />
11 }<br />
Monads are def<strong>in</strong>ed similarly to functors. The Monad concept also ref<strong>in</strong>es the<br />
ConstructorType concept. It provides two polymorphic member functions mb<strong>in</strong>d <strong>and</strong><br />
mreturn correspond<strong>in</strong>g to the follow<strong>in</strong>g <strong>Haskell</strong> signatures:<br />
1 class Monad (m :: *->*) where<br />
2 mb<strong>in</strong>d :: m x -> (x -> m y) -> m y<br />
3 mreturn :: x -> m x<br />
Us<strong>in</strong>g the previously def<strong>in</strong>ed concepts ConstructorType <strong>and</strong> Function, the signatures<br />
are translated <strong>in</strong>to the Monad concept:<br />
1 // M is a ConstructorType that is a Monad<br />
2 concept Monad : ConstructorType {<br />
3 template<br />
4 requires<br />
5 ConstructorType,<br />
6 std::SameType<br />
8 Fun::Codoma<strong>in</strong> mb<strong>in</strong>d(M::Apply, Fun);<br />
9<br />
10 template<br />
11 M::Apply mreturn(X);<br />
12 }<br />
3.2. <strong>C++</strong> Implementation of <strong>Monadic</strong> <strong>Dynamical</strong> <strong>Systems</strong><br />
In the previous section, we describe how to represent fundamental functional types.<br />
These basic build<strong>in</strong>g blocks are necessary for any library <strong>in</strong> the style we propose. In this<br />
section, we proceed to the notions specific to our doma<strong>in</strong> of vulnerability modell<strong>in</strong>g.<br />
3.2.1. The Concept Framework<br />
Us<strong>in</strong>g the concepts from the functional <strong>C++</strong> framework from the previous section,<br />
we can describe the <strong>in</strong>gredients of monadic systems. Coalgebras, which are functions<br />
of type x -> f x where f is a functor, play an important role <strong>in</strong> our framework. A<br />
general concept for a coalgebra ref<strong>in</strong>es the Function concept <strong>and</strong> adds the follow<strong>in</strong>g<br />
requirements:<br />
• the codoma<strong>in</strong> type has to be an application of a functor type (f x),<br />
• <strong>and</strong> the type the functor is applied to (x) has to be the doma<strong>in</strong> type.<br />
The Coalgebra concept expresses these requirements us<strong>in</strong>g the concepts Functor <strong>and</strong><br />
std::SameType:<br />
1 // Fun ~ x -> f x<br />
2 concept Coalgebra : Function {<br />
3 requires<br />
22
4 Functor,<br />
5 std::SameType;<br />
6 }<br />
Similarly, us<strong>in</strong>g the Monad concept, we def<strong>in</strong>e a concept for monadic coalgebras,<br />
which are functions x -> m x for a monad m. A monadic coalgebra ref<strong>in</strong>es the idea of<br />
a coalgebra <strong>with</strong> an addition of the requirement that the type constructor applied <strong>in</strong> the<br />
codoma<strong>in</strong> has to be a monad, not only a functor:<br />
1 // Fun ~ x -> m x<br />
2 concept <strong>Monadic</strong>Coalgebra : Coalgebra {<br />
3 requires Monad;<br />
4 };<br />
As seen <strong>in</strong> Sect. 2, functions of type f :: i -> x -> m x where m is a monad are<br />
of special <strong>in</strong>terest for monadic systems <strong>with</strong> an external control (realised as an <strong>in</strong>put<br />
to the system). We call such functions monadic coalgebras <strong>with</strong> <strong>in</strong>put, while functions<br />
where only a functor is required are called coalgebras <strong>with</strong> <strong>in</strong>put. The latter ref<strong>in</strong>es the<br />
concept Function2 (b<strong>in</strong>ary function) by add<strong>in</strong>g two requirements:<br />
• the codoma<strong>in</strong> type has to be a application of a functor type constructor,<br />
• <strong>and</strong> the argument <strong>in</strong> the application has to be the second doma<strong>in</strong> type.<br />
The concept <strong>Monadic</strong>CoalgebraWithInput ref<strong>in</strong>es the concept CoalgebraWithInput<br />
by stat<strong>in</strong>g that the codoma<strong>in</strong> type has to be a monad type:<br />
1 // Fun ~ (i,x) -> f x<br />
2 concept CoalgebraWithInput : Function2 {<br />
3 requires<br />
4 Functor,<br />
5 std::SameType;<br />
6 };<br />
7<br />
8 // Fun ~ (i,x) -> m x<br />
9 concept <strong>Monadic</strong>CoalgebraWithInput : CoalgebraWithInput {<br />
10 requires<br />
11 Monad;<br />
12 };<br />
Us<strong>in</strong>g that hierarchy of concepts, we specify the ma<strong>in</strong> concept of our library, the<br />
one for monadic systems:<br />
1 // Sys ~ ((t,x) -> m x)<br />
2 concept <strong>Monadic</strong>System : <strong>Monadic</strong>CoalgebraWithInput {<br />
3 typename MonoidOperation;<br />
4 requires<br />
5 Monoid,<br />
6 std::SameType;<br />
7<br />
8 // axioms (<strong>in</strong> pseudocode):<br />
9 // Sys(0) = return<br />
10 // Sys(t1 + t2) = (Sys t1
The <strong>Monadic</strong>System concept ref<strong>in</strong>es the concept for a monadic coalgebra <strong>with</strong> <strong>in</strong>put <strong>and</strong><br />
therefore <strong>in</strong>herits all requirements from there. There is just one associated entity: an<br />
associated type that represents a monoid operation on the doma<strong>in</strong> type of the monadic<br />
system. The Monoid requirement on L<strong>in</strong>e 5 implies a Function requirement, <strong>and</strong> the<br />
type identity requirement on L<strong>in</strong>e 6 ensures that the monoid element type is the same as<br />
the doma<strong>in</strong> type of the monadic system. F<strong>in</strong>ally, monadic system must obey two laws,<br />
which are expressed <strong>in</strong> comments. The first axiom states that the neutral element of the<br />
doma<strong>in</strong> monoid has to be mapped to monadic return, <strong>and</strong> the second axiom states that<br />
the b<strong>in</strong>ary operation of the monoid should be mapped to Kleisli composition.<br />
3.2.2. The Concept Framework as a Type System<br />
<strong>Concepts</strong>, such as the ones presented <strong>in</strong> this section, build the type system of our<br />
library. The doma<strong>in</strong> of vulnerability is now freed from particularity of types, <strong>and</strong> even<br />
such basic notions as functions are under the control of a user who may plug <strong>in</strong> implementations<br />
<strong>in</strong>to the <strong>in</strong>terface. Next, we give examples of generic constructors <strong>and</strong><br />
algorithms implemented <strong>in</strong> our library.<br />
In Sect. 2.3, we have <strong>in</strong>troduced a constructor for monadic systems <strong>with</strong> <strong>in</strong>put,<br />
called <strong>in</strong>put_system. Our <strong>C++</strong> library provides a similar constructor:<br />
1 // Trans ~ (i,x) -> m x; Cont ~ [i]<br />
2 template<br />
3 requires<br />
4 std::SameType<br />
5 class <strong>Monadic</strong>_System_With_Input {<br />
6 public:<br />
7 typedef Cont Doma<strong>in</strong>1;<br />
8 typedef Trans::Doma<strong>in</strong>2 Doma<strong>in</strong>2;<br />
9 typedef Trans::Codoma<strong>in</strong> Codoma<strong>in</strong>;<br />
10 typedef Concatenation Op1;<br />
11<br />
12 <strong>Monadic</strong>_System_With_Input(Trans const& trans) : my_trans(trans) {}<br />
13<br />
14 Codoma<strong>in</strong> operator()(Doma<strong>in</strong>1 const& l, Doma<strong>in</strong>2 const& x) const {<br />
15 Codoma<strong>in</strong> ret = mreturn (x);<br />
16 for (unsigned <strong>in</strong>t i=0; i
ators (operator()) must be provided as a class members though, s<strong>in</strong>ce they accesses<br />
private class variables.<br />
The monadic systems library conta<strong>in</strong>s generic functions which implement the algorithms<br />
developed <strong>in</strong> the formalisation. As an example, we discuss the macro_trj<br />
function from Sect. 2.3:<br />
1 macro_trj :: (Monad m) => (i -> (x -> m x)) -> [i] -> x -> [m x]<br />
2 macro_trj sys ts x = scanr (\i mx -> mx >>= sys i) (return x) ts<br />
The macro_trj is translated to the follow<strong>in</strong>g <strong>C++</strong> implementation:<br />
1 // Mon_Sys ~ (i,x) -> m x; Inp_Iter ~ [i]; Cont ~ [m x]<br />
2 template<br />
4 requires<br />
5 std::SameType,<br />
6 std::SameType<br />
7 Cont<br />
8 macro_trajectory(Mon_Sys const& sys,<br />
9 Inp_Iter controls_bg, Inp_Iter controls_end,<br />
10 Mon_Sys::Doma<strong>in</strong>2 x) {<br />
11 Cont macro_trj;<br />
12 std::<strong>in</strong>sert_iterator macro_trj_iter(macro_trj, macro_trj.beg<strong>in</strong>());<br />
13<br />
14 // Mon_Sys::Codoma<strong>in</strong> ~ (m x).<br />
15 *macro_trj_iter = mreturn (x);<br />
16<br />
17 Mon_Sys::Codoma<strong>in</strong>::Codoma<strong>in</strong> mx = *macro_trj.beg<strong>in</strong>();<br />
18 while(controls_bg != controls_end) {<br />
19 // Mon_Sys::Codoma<strong>in</strong> ~ (m x) is the monad type.<br />
20 // mb<strong>in</strong>d is called for that monad m.<br />
21 mx = mb<strong>in</strong>d(mx, curry(sys)(*controls_bg)); ++controls_bg;<br />
22 ++macro_trj_iter; *macro_trj_iter = mx;<br />
23 }<br />
24<br />
25 return macro_trj;<br />
26 }<br />
The two l<strong>in</strong>es <strong>in</strong> <strong>Haskell</strong> correspond to a much longer implementation <strong>in</strong> <strong>C++</strong>. Most<br />
of the verbosity is due to concept-based type signature. It should be noted that we use<br />
the <strong>C++</strong> iterator mechanism to implement a function which is even more generic than<br />
the equivalent <strong>Haskell</strong> version: <strong>in</strong> contrast to the <strong>Haskell</strong> function, where we h<strong>and</strong>le all<br />
sequences as <strong>Haskell</strong> lists, we do not have a fixed sequence type for the <strong>in</strong>put (nor for<br />
the output) <strong>in</strong> the <strong>C++</strong> version. On the other h<strong>and</strong>, we have not reimplemented <strong>Haskell</strong>’s<br />
scanr, which makes our implementation more verbose.<br />
In addition to the constructors <strong>and</strong> generic algorithms we shown here our library<br />
provides also comb<strong>in</strong>ators, <strong>in</strong> particular <strong>Monadic</strong>_<strong>Systems</strong>_Parallel <strong>and</strong><br />
Sys_Ser_Function. As a f<strong>in</strong>al example how our libraries can be used we<br />
present a vulnerability computation algorithm encoded <strong>with</strong> the concepts from our libraries<br />
<strong>in</strong> the next section.<br />
25
3.3. Application of the <strong>Monadic</strong> <strong>Systems</strong> Library <strong>in</strong> Vulnerability Assessment<br />
The framework of concepts, operation <strong>and</strong> comb<strong>in</strong>ators presented so far can be<br />
used to implement vulnerability computation as <strong>in</strong>troduced <strong>in</strong> Sect. 2.3. The signature<br />
of such computations, as for <strong>in</strong>stance<br />
1 vulnerability’ :: (Functor m, Monad m) =><br />
2 (i -> x -> m x) -> ([x] -> h) -><br />
3 (m h -> v) -> [i] -> x -> v<br />
4 vulnerability’ sys harm measure ts = measure . fmap harm . micro_trj sys ts<br />
has to be encoded <strong>with</strong> requirements. For functions types we use the Function concept,<br />
<strong>and</strong> type identities are expressed <strong>with</strong> std::SameType requirements:<br />
1 template<br />
3 requires<br />
4 ConstructorType, Monad,<br />
5 std::SameType,<br />
6 std::SameType,<br />
7 std::SameType<br />
8 Meas::Codoma<strong>in</strong><br />
9 vulnerability_sys(Sys sys, Harm harm, Meas measure, Crtl ts,<br />
10 Sys::Doma<strong>in</strong>2 x) {<br />
11 typedef<br />
12 Sys::Codoma<strong>in</strong>::Apply<br />
13 Micro_Trj_Type;<br />
14<br />
15 Micro_Trj_Type micro_trj;<br />
16<br />
17 micro_trajectories(sys, x, ts.beg<strong>in</strong>(), ts.end(), micro_trj);<br />
18 return measure(fmap (harm, micro_trj));<br />
19 }<br />
It should be noted that encod<strong>in</strong>g the function signature <strong>with</strong> concepts is more complex<br />
than the functional signature. Otherwise the implementation is not much different from<br />
the functional implementation because technical details such as the iterator mechanism<br />
are hidden <strong>in</strong> the computation of micro-trajectories.<br />
4. Reimplementation <strong>in</strong> concept-based <strong>Haskell</strong><br />
The general concepts presented <strong>in</strong> section Sect. 3.2 are not only implementable <strong>in</strong><br />
<strong>C++</strong> but also <strong>in</strong> any language which provides an appropriate support of generic programm<strong>in</strong>g<br />
<strong>with</strong> concepts. To illustrate what implementations <strong>in</strong> other languages could<br />
look like, we sketch a monadic systems library <strong>in</strong> concept-based <strong>Haskell</strong>.<br />
Recent additions of support for associated types to the GHC <strong>Haskell</strong> compiler<br />
(Chakravarty et al., 2005; Schrijvers et al., 2008) allows us to express the <strong>C++</strong> concept<br />
framework also <strong>in</strong> <strong>Haskell</strong> (<strong>with</strong> extensions). We have ported our <strong>C++</strong> implementation<br />
“back to <strong>Haskell</strong>” <strong>and</strong> <strong>in</strong>terest<strong>in</strong>g future work would be to make this port more complete<br />
<strong>and</strong> to compare the expressivity <strong>and</strong> efficiency of the generated code. Below is a<br />
sample of the <strong>Haskell</strong> version us<strong>in</strong>g associated types. The full <strong>Haskell</strong> development is<br />
26
available as an experimental Cabal package <strong>with</strong> 43 modules <strong>and</strong> 1700 LOC (<strong>in</strong>clud<strong>in</strong>g<br />
comments).<br />
We start <strong>with</strong> the Function concept as a <strong>Haskell</strong> type class <strong>with</strong> a st<strong>and</strong>ard modell<strong>in</strong>g<br />
(<strong>in</strong>stance) for the built-<strong>in</strong> function type. As <strong>Haskell</strong> does not allow overload<strong>in</strong>g<br />
the application operator, we use an <strong>in</strong>fix operator (!):<br />
1 class Function fun where<br />
2 type Doma<strong>in</strong> fun<br />
3 type Codoma<strong>in</strong> fun<br />
4 (!) :: fun -> (Doma<strong>in</strong> fun -> Codoma<strong>in</strong> fun)<br />
5<br />
6 <strong>in</strong>stance Function (a -> b) where<br />
7 type Doma<strong>in</strong> (a -> b) = a<br />
8 type Codoma<strong>in</strong> (a -> b) = b<br />
9 f ! x = f x<br />
Next, we move to the ConstructorType concept where we use GHC’s support for<br />
<strong>in</strong>fix type constructors to make later def<strong>in</strong>itions a bit more readable.<br />
1 class ConstructorType con where<br />
2 data (:@) con :: * -> *<br />
3 type Apply = (:@)<br />
The full code also <strong>in</strong>cludes three more associated entities.<br />
For the next example (monads) we need equality constra<strong>in</strong>ts: a ~ b is the <strong>Haskell</strong><br />
equivalent of SameType <strong>in</strong> <strong>C++</strong> <strong>with</strong> <strong>Concepts</strong>. We name the Function type variable<br />
a2mb (short for “a to m b”):<br />
1 class ConstructorType m => Monad m where<br />
2 mb<strong>in</strong>d :: (Function a2mb, Codoma<strong>in</strong> a2mb ~ (m :@ b)) =><br />
3 m :@ Doma<strong>in</strong> a2mb -> a2mb -> Codoma<strong>in</strong> a2mb<br />
4 mreturn :: a -> m:@a<br />
Note that the equality constra<strong>in</strong>t means that the same type can be expressed <strong>in</strong> different<br />
ways: <strong>in</strong> this example Codoma<strong>in</strong> a2mb can freely be replaced by m:@b. In general,<br />
not only can equals be substituted for equals, but we can also effectively add type<br />
subexpression aliases as <strong>in</strong> the follow<strong>in</strong>g example:<br />
1 mb<strong>in</strong>d’ :: ( Monad m, Function a2mb<br />
2 , a ~ Doma<strong>in</strong> a2mb<br />
3 , mb ~ Codoma<strong>in</strong> a2mb<br />
4 , ma ~ (m :@ a)<br />
5 , mb ~ (m :@ b)<br />
6 ) =><br />
7 ma -> a2mb -> mb<br />
8 mb<strong>in</strong>d’ = mb<strong>in</strong>d<br />
In fact, equality constra<strong>in</strong>ts are sufficiently powerful to take us to the limit of what<br />
GHC can h<strong>and</strong>le. When encod<strong>in</strong>g the Coalgebra concept we had to comment out the<br />
equality constra<strong>in</strong>t to avoid a compiler error 5 :<br />
5 Both GHC 6.12 <strong>and</strong> GHC 7.0.1 say “The current implementation of type families does not support<br />
equality constra<strong>in</strong>ts <strong>in</strong> superclass contexts. They are planned for a future release.”<br />
27
1 class ( Function a2fb<br />
2 , Functor (FunctorTag a2fb)<br />
3 -- , Codoma<strong>in</strong> a2fb ~ (FunctorTag a2fb :@ Doma<strong>in</strong> a2fb)<br />
4 ) => Coalgebra a2fb where<br />
5 type FunctorTag a2fb :: *<br />
Our f<strong>in</strong>al example (<strong>in</strong> Fig. 4) is the generic vulnerability calculation where we use<br />
equality constra<strong>in</strong>ts to document the type structure <strong>in</strong> detail (mak<strong>in</strong>g it just as verbose<br />
as the <strong>C++</strong> version).<br />
1 vulnerability_sys ::<br />
2 ( <strong>Monadic</strong>System sys , Function harm<br />
3 , i ~ Doma<strong>in</strong> sys , [x] ~ Doma<strong>in</strong> harm<br />
4 , x2mx ~ Codoma<strong>in</strong> sys , h ~ Codoma<strong>in</strong> harm<br />
5 , x ~ Doma<strong>in</strong> x2mx , Function meas<br />
6 , mx ~ Codoma<strong>in</strong> x2mx , mh ~ Doma<strong>in</strong> meas<br />
7 , m ~ FunctorTag x2mx , v ~ Codoma<strong>in</strong> meas<br />
8 , mx ~ (m:@x) , mh ~ (m :@ h)<br />
9 ) => sys -> harm -> meas -> [i] -> x -> v<br />
10 vulnerability_sys sys harm meas is x = v<br />
11 where mxs = micro_trj sys is x<br />
12 mh = fmap harm mxs<br />
13 v = meas ! mh<br />
Figure 4: The generic vulnerability calculation <strong>in</strong> <strong>Haskell</strong> <strong>with</strong> concepts.<br />
While port<strong>in</strong>g the concepts code from <strong>C++</strong> to <strong>Haskell</strong> we had to make a number<br />
of technical choices (associated types versus associated datatypes, type <strong>in</strong>ference versus<br />
explicit type application, etc.) where the languages differ. A detailed description<br />
would take as too far off topic but there is certa<strong>in</strong>ly some scope for future work <strong>in</strong> this<br />
direction.<br />
One issue that deserves attention, however, is our use of associated datatypes. An<br />
attentive reader may have noticed that the <strong>Haskell</strong> ConstructorType concept does not<br />
impose the same constra<strong>in</strong>ts on the tag as the <strong>C++</strong> version on page 20. <strong>Haskell</strong>’s associated<br />
datatype <strong>in</strong>troduces a wrapper, which is one of the solutions we discussed <strong>in</strong><br />
the discussion of the <strong>C++</strong> ConstructorType concept. Thanks to that wrapper, one can<br />
always map a constructor type application back to the appropriate <strong>in</strong>stance, avoid<strong>in</strong>g<br />
<strong>in</strong>jectivity errors 6 . Yet, the wrapper does not come <strong>with</strong>out a price. The programmer<br />
must now wrap <strong>and</strong> unwrap values where necessary, which is impossible to do<br />
generically. To avoid that issue, the actual ConstructorType class <strong>in</strong>troduces extra<br />
mach<strong>in</strong>ery:<br />
1 class ConstructorType con where<br />
2 data (:@) con :: * -> *<br />
3 type Applied con :: * -> *<br />
4 unapply :: con :@ a > Applied con a<br />
6 http://www.haskell.org/haskellwiki/GHC/Type_families<br />
28
Constructor type application produces a wrapped value, but we also provide generic<br />
apply <strong>and</strong> unapply functions that can move back <strong>and</strong> forth between wrapped <strong>and</strong> unwrapped<br />
values. The associated type Applied corresponds to the Apply template <strong>in</strong> the<br />
<strong>C++</strong> version of this concept.<br />
5. Related Work<br />
In the realm of generic programm<strong>in</strong>g, the use of concepts (or type classes) to abstract<br />
from representations of data or to capture certa<strong>in</strong> properties of types is a common<br />
practise. For example, the <strong>C++</strong> St<strong>and</strong>ard Template Library (STL) (Austern, 1998;<br />
Stepanov <strong>and</strong> Lee, 1994) <strong>in</strong>troduces a hierarchy of concepts for data conta<strong>in</strong>ers <strong>and</strong> for<br />
iterators used to generically traverse ranges of data, <strong>and</strong> the Boost Graph Library (Siek<br />
et al., 2002) <strong>in</strong>troduces concepts represent<strong>in</strong>g different k<strong>in</strong>ds of graphs. In the traditional<br />
approach, functional notions such as monadic system, for example, are either<br />
not represented explicitly at all (<strong>in</strong> <strong>C++</strong> libraries) or are represented by a particular type<br />
(as <strong>in</strong> <strong>Haskell</strong> libraries). In our generic library for vulnerability assessment, we take<br />
abstraction further <strong>in</strong> conceptually represent<strong>in</strong>g functions as well as data. In <strong>Haskell</strong>,<br />
almost all libraries are generic <strong>in</strong> the sense that they use <strong>and</strong> def<strong>in</strong>e type classes. Some<br />
more advanced examples are (Chakravarty et al., 2005; Claessen <strong>and</strong> Hughes, 2000;<br />
Jansson <strong>and</strong> Jeur<strong>in</strong>g, 2002; Oliveira et al., 2006)<br />
Recently, new concept applications have been enabled (<strong>and</strong> <strong>in</strong>spired) by the l<strong>in</strong>guistic<br />
support for concepts <strong>in</strong> <strong>C++</strong>0x (Gregor et al., 2006). For example, much of the st<strong>and</strong>ard<br />
library of <strong>C++</strong> (<strong>in</strong>clud<strong>in</strong>g the STL) has been conceptualised, that is, rewritten us<strong>in</strong>g<br />
the new concepts feature (for example, Gregor et al., 2008a,b). This body of code <strong>and</strong><br />
specifications provides a good example of how generic libraries will be written when<br />
concepts officially become a feature of <strong>C++</strong>. Our work goes further than STL concepts.<br />
The first difference is that we systematically tackle type constructor concepts; the only<br />
similar concept <strong>in</strong> STL is the Allocator concept (Halpern, 2008), which requires compiler<br />
support to verify constra<strong>in</strong>ts that are expressed us<strong>in</strong>g SameTypeConstructor concept<br />
<strong>in</strong> our framework. The other difference is <strong>in</strong> h<strong>and</strong>l<strong>in</strong>g of computations: <strong>in</strong> our<br />
framework a computation is represented by a self-conta<strong>in</strong>ed Function concept that<br />
knows its doma<strong>in</strong> <strong>and</strong> codoma<strong>in</strong> types, while <strong>in</strong> the conceptualised STL a computation<br />
is represented by a Callable family of concepts that require doma<strong>in</strong> types as concept<br />
arguments.<br />
One aspect of our work is implementation of functional programm<strong>in</strong>g constructs<br />
<strong>in</strong> <strong>C++</strong>. Related work has been done before, <strong>in</strong>clud<strong>in</strong>g the Boost Lambda library (Järvi<br />
et al., 2003), the F<strong>C++</strong> library (McNamara <strong>and</strong> Smaragdakis, 2004b), <strong>and</strong> the Boost<br />
Fusion library (de Guzman <strong>and</strong> Marsden, 2009). All the previous approaches rely<br />
heavily on template meta-programm<strong>in</strong>g, while we encode the types of functions on the<br />
level of concepts.<br />
A related project <strong>with</strong> similar goals as our work is the DUNE (Distributed <strong>and</strong> Unified<br />
Numerics Environment) project (Bastian et al., 2008). DUNE identifies an abstract<br />
specification of a parallel <strong>and</strong> adaptive hierarchical grid for scientific comput<strong>in</strong>g, but<br />
<strong>with</strong>out provid<strong>in</strong>g a functional prototype implementation. <strong>C++</strong> template programm<strong>in</strong>g<br />
is employed to achieve an efficient implementation of this specification which supports<br />
29
<strong>with</strong> reuse of exist<strong>in</strong>g f<strong>in</strong>ite element packages. <strong>Concepts</strong> are used implicitly to specific<br />
the type parameters of the templates.<br />
Botta <strong>and</strong> Ionescu develop a generic <strong>C++</strong> library for parallel comput<strong>in</strong>g us<strong>in</strong>g a<br />
<strong>Haskell</strong> prototype as a model <strong>and</strong> a specification. While concepts are not used explicitly<br />
there is a common idea between their work <strong>and</strong> the approach presented <strong>in</strong> this paper.<br />
This paper can also be seen as cont<strong>in</strong>u<strong>in</strong>g the l<strong>in</strong>e of work relat<strong>in</strong>g concepts <strong>in</strong><br />
<strong>Haskell</strong> <strong>and</strong> <strong>C++</strong>: (Bernardy et al., 2010, 2008; Garcia et al., 2007b; Zalewski et al.,<br />
2007).<br />
6. Discussion <strong>and</strong> Future Work<br />
We presented an approach to express doma<strong>in</strong> notions <strong>in</strong> a functional model <strong>and</strong> afterwards<br />
transform them <strong>in</strong>to generic concepts. This enables us to implement doma<strong>in</strong>specific<br />
high-performance libraries from functional models. We have illustrated our<br />
approach by implement<strong>in</strong>g a library for monadic dynamical systems, a useful model of<br />
systems <strong>in</strong>volved <strong>in</strong> vulnerability modell<strong>in</strong>g <strong>in</strong> the context of climate change. A functional<br />
description of monadic dynamical systems <strong>and</strong> algorithms is provided <strong>in</strong> the first<br />
part of this paper, <strong>in</strong> the second part we implement a concept-based generic <strong>C++</strong> library<br />
from this executable functional specification.<br />
Our approach is flexible, we don’t have to stick to <strong>C++</strong> <strong>and</strong> <strong>Haskell</strong>. The functional<br />
modell<strong>in</strong>g can be done <strong>in</strong> other functional languages or even <strong>in</strong> a more mathematical<br />
notion like the typed λ-calculus. As we have shown, the implementation of the f<strong>in</strong>al<br />
library can also be done <strong>in</strong> concept-enabled <strong>Haskell</strong>. But what language features are<br />
necessary to apply our approach? First of all, the language has to provide a mechanism<br />
to allow generic programm<strong>in</strong>g <strong>with</strong> concepts. This <strong>in</strong>clude a possibility to implement<br />
concepts, a notion for ref<strong>in</strong>ement, a mechanism for modell<strong>in</strong>g <strong>and</strong> support for<br />
constra<strong>in</strong><strong>in</strong>g generic algorithms. Besides, Bernardy et al. studies advanced language<br />
features for generic programm<strong>in</strong>g <strong>with</strong> concepts. Fig. 5 summarises language features<br />
which are necessary for implement<strong>in</strong>g a generic library <strong>with</strong> our approach. Only a few<br />
Feature<br />
Necessary for<br />
Multi-type concepts <strong>Concepts</strong> modell<strong>in</strong>g type identities as for <strong>in</strong>stance <strong>in</strong> std::SameType<br />
Multiple constra<strong>in</strong>ts Encod<strong>in</strong>g complex function signatures as <strong>in</strong> vulnerability_sys<br />
Parametric modell<strong>in</strong>g Declare models for our ConstructorType concept<br />
Associated type access Encod<strong>in</strong>g function signatures of member functions, for <strong>in</strong>stance mb<strong>in</strong>d <strong>in</strong><br />
Monad.<br />
Constra<strong>in</strong>ts on associated<br />
types<br />
Encod<strong>in</strong>g type relations between associated types <strong>and</strong> type parameters,<br />
for <strong>in</strong>stance <strong>in</strong> the ConstructorType concept.<br />
Type equality constra<strong>in</strong>ts Encod<strong>in</strong>g type equalities <strong>in</strong> complex function signatures as <strong>in</strong><br />
vulnerability_sys<br />
Figure 5: Language features (us<strong>in</strong>g term<strong>in</strong>ology from Bernardy et al.)<br />
concept-based generic library <strong>with</strong> our approach.<br />
that are necessary to develop a<br />
features are really essential, while some other features (like constra<strong>in</strong>t <strong>and</strong> type aliases)<br />
are useful for more convenient cod<strong>in</strong>g but not necessary for implement<strong>in</strong>g a library.<br />
The transformation of types from a functional style <strong>in</strong>to Function-concept style<br />
follows a well def<strong>in</strong>ed scheme <strong>and</strong> can therefore be automated. In a nutshell, a function<br />
30
type f :: X -> Y is flattened by replac<strong>in</strong>g higher order function types <strong>in</strong> the doma<strong>in</strong><br />
type <strong>and</strong> the codoma<strong>in</strong> type. Higher order function types <strong>in</strong> the doma<strong>in</strong> are replaced by<br />
type parameters <strong>and</strong> concepts are used to encode their signature. In the codoma<strong>in</strong> type,<br />
a new type is <strong>in</strong>troduced for every higher order function type <strong>and</strong> the orig<strong>in</strong>al higher<br />
order function type is replaced by it. We currently work<strong>in</strong>g on a compiler that does this<br />
transformation. 7<br />
Acknowledgements<br />
The authors would like to thank Jean-Philippe Bernardy, Nicola Botta, Andreas<br />
Priesnitz, Gustav Munkby <strong>and</strong> Sibylle Schupp for their <strong>in</strong>sightful comments <strong>and</strong> <strong>in</strong>terest<strong>in</strong>g<br />
discussions. The research <strong>in</strong> this paper was partly supported by a grant from the<br />
European Union research project ADAM under Contract number GOCE-018476 <strong>and</strong><br />
by a grant 0702717 from National Science Foundation.<br />
References<br />
Adger, W. N., 2006. Vulnerability. Global Environmental Change 16, 268–281.<br />
Austern, M. H., 1998. Generic Programm<strong>in</strong>g <strong>and</strong> the STL: Us<strong>in</strong>g <strong>and</strong> Extend<strong>in</strong>g the<br />
<strong>C++</strong> St<strong>and</strong>ard Template Library. Addison-Wesley.<br />
Bastian, P., Blatt, M., Dedner, A., Engwer, C., Klöfkorn, R., Kornhuber, R., Ohlberger,<br />
M., S<strong>and</strong>er, O., July 2008. A generic grid <strong>in</strong>terface for parallel <strong>and</strong> adaptive scientific<br />
comput<strong>in</strong>g. part ii: implementation <strong>and</strong> tests <strong>in</strong> dune. Comput<strong>in</strong>g 82, 121–138.<br />
Bernardy, J.-P., Jansson, P., Zalewski, M., Schupp, S., 2010. Generic programm<strong>in</strong>g<br />
<strong>with</strong> <strong>C++</strong> concepts <strong>and</strong> <strong>Haskell</strong> type classes—a comparison. J. Funct. Program.In<br />
press.<br />
Bernardy, J.-P., Jansson, P., Zalewski, M., Schupp, S., Priesnitz, A., 2008. A comparison<br />
of <strong>C++</strong> concepts <strong>and</strong> <strong>Haskell</strong> type classes. In: Proc. ACM SIGPLAN Workshop<br />
on Generic Programm<strong>in</strong>g. ACM, pp. 37–48.<br />
Botta, N., Ionescu, C., 2007. Relation-Based Computations <strong>in</strong> a <strong>Monadic</strong> BSP Model.<br />
Parallel Comput<strong>in</strong>g 33 (12), 795–821.<br />
Brooks, N., 2003. Vulnerability, risk <strong>and</strong> adaptation: A conceptual framework. Tyndall<br />
Center Work<strong>in</strong>g Paper 38.<br />
Chakravarty, M. M. T., Keller, G., Jones, S. P., 2005. Associated type synonyms. In:<br />
ICFP ’05: Proc. tenth ACM SIGPLAN <strong>in</strong>ternational conference on Functional programm<strong>in</strong>g.<br />
ACM, pp. 241–253.<br />
7 See the project page http://www.pik-potsdam.de/members/l<strong>in</strong>cke/haskc-generic-c-programm<strong>in</strong>g-fromhaskell-specification<br />
31
Claessen, K., Hughes, J., 2000. QuickCheck: A lightweight tool for r<strong>and</strong>om test<strong>in</strong>g of<br />
<strong>Haskell</strong> programs. In: ICFP’00: International Conference on Functional Programm<strong>in</strong>g.<br />
ACM, pp. 268–279.<br />
Garcia, R., Jarvi, J., Lumsda<strong>in</strong>e, A., Siek, J., Willcock, J., Mar. 2007a. An extended<br />
comparative study of language support for generic programm<strong>in</strong>g. J. Funct. Program.<br />
17 (2), 145–205.<br />
Garcia, R., Jarvi, J., Lumsda<strong>in</strong>e, A., Siek, J., Willcock, J., 2007b. An extended comparative<br />
study of language support for generic programm<strong>in</strong>g. J. Funct. Program. 17 (2),<br />
145–205.<br />
Gregor, D., Järvi, J., Siek, J., Stroustrup, B., Dos Reis, G., Lumsda<strong>in</strong>e, A., 2006.<br />
<strong>Concepts</strong>: L<strong>in</strong>guistic support for generic programm<strong>in</strong>g <strong>in</strong> <strong>C++</strong>. In: Proc. ACM SIG-<br />
PLAN Conf. on Object-Oriented Programm<strong>in</strong>g, <strong>Systems</strong>, Languages, <strong>and</strong> Applications<br />
(OOPSLA). ACM Press, pp. 291–310.<br />
Gregor, D., Marcus, M., Witt, T., Lumsda<strong>in</strong>e, A., 2008a. Foundational concepts<br />
for the <strong>C++</strong>0x st<strong>and</strong>ard library (rev. 4). Tech. Rep. N2737=08-0247, ISO/IEC<br />
JTC1/SC22/WG21 - <strong>C++</strong>.<br />
Gregor, D., Siek, J., Lumsda<strong>in</strong>e, A., 2008b. Iterator concepts for the <strong>C++</strong>0x st<strong>and</strong>ard<br />
library (rev. 4). Tech. Rep. N2739=08-0249, ISO/IEC JTC1/SC22/WG21 - <strong>C++</strong>.<br />
Gregor, D., Stroustrup, B., Widman, J., Siek, J., 2008c. Proposed word<strong>in</strong>g for concepts<br />
(rev. 8). Tech. Rep. N2741=08-0251, ISO/IEC JTC1/SC22/WG21 - <strong>C++</strong>.<br />
de Guzman, J., Marsden, D., 2009. Fusion library homepage. http://www.boost.org/<br />
libs/fusion.<br />
Halpern, P., 2008. Defects <strong>and</strong> proposed resolutions for allocator concepts. Tech. Rep.<br />
N2810=08-0320, ISO/IEC JTC1/SC22/WG21 - <strong>C++</strong>.<br />
Ionescu, C., 2009. Vulnerability modell<strong>in</strong>g <strong>and</strong> monadic dynamical systems. Ph.D.<br />
thesis, Freie Universität Berl<strong>in</strong>, available from http://www.diss.fu-berl<strong>in</strong>.de/<br />
diss/receive/FUDISS_thesis_000000008403.<br />
Janssen, M. A., Ostrom, E., 2006. Resilience, vulnerability <strong>and</strong> adaptation: A crosscutt<strong>in</strong>g<br />
theme of the <strong>in</strong>ternational human dimensions programme on global environmental<br />
change. Global Environmental Change 16 (3), 237–239, editorial.<br />
Jansson, P., Jeur<strong>in</strong>g, J., 2002. Polytypic data conversion programs. Science of Computer<br />
Programm<strong>in</strong>g 43 (1), 35–75.<br />
Järvi, J., Powell, G., Lumsda<strong>in</strong>e, A., 2003. The lambda library: Unnamed functions <strong>in</strong><br />
<strong>C++</strong>. Software: Practice <strong>and</strong> Experience 33 (3), 259–291.<br />
Jones, M. P., 1993. A system of constructor classes: overload<strong>in</strong>g <strong>and</strong> implicit higherorder<br />
polymorphism. In: Proc. Conference on Functional Programm<strong>in</strong>g Languages<br />
<strong>and</strong> Computer Architecture (FPCA). ACM, New York, NY, USA, pp. 52–61.<br />
32
K<strong>in</strong>g, D., Wadler, P., 1992. Comb<strong>in</strong><strong>in</strong>g monads. In: Launchbury, J., Sansom, P. M.<br />
(Eds.), Glasgow Workshop on Functional Programm<strong>in</strong>g. Spr<strong>in</strong>ger-Verlag, pp. 134–<br />
143.<br />
L<strong>in</strong>cke, D., 2010. Functional <strong>C++</strong> <strong>with</strong> concepts. Last checked: 2010-12-27.<br />
L<strong>in</strong>cke, D., Jansson, P., Zalewski, M., Ionescu, C., 2009. Generic libraries <strong>in</strong> <strong>C++</strong> <strong>with</strong><br />
concepts from high-level doma<strong>in</strong> descriptions <strong>in</strong> <strong>Haskell</strong>: A DSL for computational<br />
vulnerability assessment. In: IFIP Work<strong>in</strong>g Conf. on Doma<strong>in</strong> Specific Languages.<br />
Vol. 5658/2009 of LNCS. pp. 236–261.<br />
L<strong>in</strong>cke, D., Schupp, S., 2009. The function concept <strong>in</strong> <strong>C++</strong>- an empirical study. In:<br />
WGP ’09: Proc. ACM SIGPLAN workshop on Generic programm<strong>in</strong>g. ACM, pp.<br />
25–36.<br />
McNamara, B., Smaragdakis, Y., 2004a. Functional programm<strong>in</strong>g <strong>with</strong> the fc++ library.<br />
Journal of Functional Programm<strong>in</strong>g 14 (4), 429–472.<br />
McNamara, B., Smaragdakis, Y., 2004b. Functional programm<strong>in</strong>g <strong>with</strong> the F<strong>C++</strong> library.<br />
J. of Functional Programm<strong>in</strong>g 14 (4), 429–472.<br />
Myers, N., 1995. A new <strong>and</strong> useful template technique: “Traits”. <strong>C++</strong> Report 7 (5), 35,<br />
32.<br />
Oliveira, B. C. d. S., H<strong>in</strong>ze, R., Löh, A., 2006. Extensible <strong>and</strong> modular generics for the<br />
masses. In: Nilsson, H. (Ed.), Trends <strong>in</strong> Functional Programm<strong>in</strong>g. pp. 199–216.<br />
Petoukhov, V., Ganopolski, A., Brovk<strong>in</strong>, V., Claussen, M., Eliseev, A., Kubatzki, C.,<br />
Rahmstorf, S., 2000. CLIMBER-2 : a climate system model of <strong>in</strong>termediate complexity.<br />
Part I : model description <strong>and</strong> performance for present climate. Climate dynamics<br />
16, 1–17.<br />
Peyton Jones, S. (Ed.), 2003. <strong>Haskell</strong> 98 Language <strong>and</strong> Libraries: The Revised Report.<br />
Cambridge University Press.<br />
Schrijvers, T., Peyton Jones, S., Chakravarty, M., Sulzmann, M., 2008. Type check<strong>in</strong>g<br />
<strong>with</strong> open type functions. In: ICFP ’08: Proc. 13th ACM SIGPLAN <strong>in</strong>ternational<br />
conference on Functional programm<strong>in</strong>g. ACM, pp. 51–62.<br />
Siek, J. G., Lee, L. Q., Lumsda<strong>in</strong>e, A., 2002. The Boost Graph Library: User Guide<br />
<strong>and</strong> Reference Manual. Addison-Wesley.<br />
Stepanov, A. A., Lee, M., 1994. The St<strong>and</strong>ard Template Library. Tech. Rep. HPL-94-<br />
34, Hewlett-Packard Laboratories, revised <strong>in</strong> October 1995 as tech. rep. HPL-95-11.<br />
Stroustrup, B., 1997. The <strong>C++</strong> Programm<strong>in</strong>g Language, 3rd Edition. Addison-Wesley.<br />
Wadler, P., Blott, S., 1989. How to make ad-hoc polymorphism less ad hoc. In: Proc.<br />
16th ACM SIGPLAN-SIGACT Symp. on Pr<strong>in</strong>ciples of Programm<strong>in</strong>g Languages<br />
(POPL). ACM Press, pp. 60–76.<br />
33
Wolf, S., L<strong>in</strong>cke, D., H<strong>in</strong>kel, J., Ionescu, C., Bisaro, S., 2008. A formal framework<br />
of vulnerability. F<strong>in</strong>al deliverable to the ADAM project. FAVAIA work<strong>in</strong>g paper 8,<br />
Potsdam Institute for Climate Impact Research, Potsdam, Germany.<br />
Zalewski, M., Priesnitz, A. P., Ionescu, C., Botta, N., Schupp, S., 2007. Multi-<br />
Language library development: From <strong>Haskell</strong> type classes to <strong>C++</strong> concepts. In:<br />
Striegnitz, J. (Ed.), Proc. 6th Int. Workshop on Multiparadigm Programm<strong>in</strong>g With<br />
Object-Oriented Languages (MPOOL).<br />
34