<<

FunZ: An Intermediate Specification Language

LINDA B. SHERRELL1 AND DORIS L. CARVER Department of , Louisiana State University, Baton Rouge, LA 70803, USA Email: [email protected] [email protected]

During the last few years, the field of software engineering has witnessed an increased interest in and software reuse. At the same time, functional programming languages, often espoused as rapid prototyping tools, have begun to enjoy more mainstream usage. Assuming that these trends continue, software developers will need improved methods to transform existing specifications into functional implementations. In this paper, we discuss the intermediate specification language FunZ, an integral part of a methodology to produce purely functional programs from Z specifications. To illustrate the concepts of FunZ, we specify the design of a simple software system using both the and that of FunZ. FunZ itself is best described as an extension of Haskell, yet the language also retains a Downloaded from https://academic.oup.com/comjnl/article/38/3/193/359139 by guest on 30 September 2021 Z-like flavour in that it contains notational conventions similar to those of standard Z and several object-oriented variants. In addition, software design with FunZ parallels the activity in Z except that each step has functional overtones to better accommodate a final implementation in a purely functional language.

Received September 16, 1994; revised May 5, 1995

1. INTRODUCTION The use of functional programming languages should As the complexity and cost of software have continually become even more prevalent in the future with ongoing increased, researchers have attempted to alleviate the improvements to compilers and advances in computer software crisis. Several approaches have been initiated. architecture. At the same time, the current emphasis on Formal methods have been introduced into the software formal methods and software reuse is likely to continue. lifecycle. Support tools have been implemented to help Therefore, we have designed the intermediate language eliminate human error. Programming paradigms other FunZ and an associated methodology to aid software than the conventional, imperative model have been developers in deriving purely functional programs from advocated. existing Z specifications. One such paradigm is functional programming. Several languages have influenced the design of FunZ Functional languages offer powerful abstraction facilities, including Larch [10], COLD-K [11], Extended ML [12] which allow algorithms to be expressed in a natural and and Object-Z [13]. Ideas from [14] have also played a role concise fashion. As a sample, higher-order functions, list in its development. However, FunZ is best described as comprehensions, pattern matching and lazy evaluation are an extension of Haskell with a Z-like flavour because it devices available to the modern functional programmer. preserves many of the notational conventions of standard Z and several object-oriented variants. In In the past, although functional languages were addition, software design with FunZ is similar to frequently used in the realm of rapid prototyping [1], that with Z, except that each step has functional [2] and [3], mainstream applications were somewhat overtones in order to provide a better match with a limited. However, over the last few years, this trend has final implementation in a purely functional language. begun to change. For example, Lolita [4], a large system for natural language processing, was developed com- Since FunZ combines features from both Z and pletely in Miranda™ [5].2 Clio and Spectool, two Haskell, the language is of benefit to either Z or Haskell verification tools designed at Odyssey Research aficionados. In particular, for those software developers Associates, are based on Caliban, a Miranda-like who know Z but are less familiar with functional language. These tools played a major role in the first programming, FunZ provides a bridge between Z phase of verifying a hardware component for the Fault specifications and functional implementations. Similarly, Tolerant Parallel Processor [6]. More recently, Haskell for those Haskell programmers inexperienced with Z, [7] has been used to program a significant portion of a FunZ is an attractive design language because it is a software system for automatic speech recognition [8]. simple extension of Haskell. Additional real-world applications can be found in [9]. In addition, using FunZ for design specifications as opposed to Z offers several advantages to both groups. First, code fragments are derived and verified earlier in 1 Present address: Department of Computer Science and Mathe- the development process. Consequently, the total cost matics, Arkansas State University, PO Box 70, Arkansas 72467-0070, USA. for a software project should decrease. Second, FunZ 2 ™ Miranda is a trademark of Research Software Ltd. allows a developer to prove properties about the system

THE COMPUTER JOURNAL, VOL.38, No. 3, 1995 r

194 L. B. SHERRELL AND D. L. CARVER

design using either the Z notation or the programming schemas to specification statements in the refinement language Haskell. This freedom means that the notation calculus [23] and then apply the laws of the calculus to most applicable to the problem may be selected. And derive guarded command programs. In [24] the translation finally, the methodology surrounding FunZ provides a occurs after data reification in Z, while [25] initiates the framework for recording design decisions that is useful change in notation one step sooner by converting the for future maintenance. abstract specification schemas to the refinement calculus. We have experimented with changing from Z to 1.1. Why Z and Haskell? Haskell at different stages in the software life cycle. We began with a traditional approach, that is, refining Z Throughout their respective histories, specification specifications to Z designs and then to code. Initial languages and functional programming languages have designs focused on the list and its standard list functions, been closely associated. Hope [15], an early functional while later designs targeted additional data types, most language, includes parameterized modules that are based notably the array. The respective translations revealed a

on those of CLEAR [16], the first algebraic specification Downloaded from https://academic.oup.com/comjnl/article/38/3/193/359139 by guest on 30 September 2021 language. At least two prototyping languages, me too [1] natural correspondence between sequences and func- and SAMPAE [17], combine features from Miranda and tions in Z and lists and arrays in Haskell. The interested VDM, the first formal method to use the model-oriented reader can find detailed descriptions of some of these approach. And now, as a means of bridging the gap designs and translations in [26] and [27]. between Z specifications and Haskell implementations, To formalize this work, we needed to solve two FunZ continues this tradition by integrating features problems: (i) adapt the traditional refinement approach from Z and Haskell. [18] in order to give it a more functional flavour and (ii) define a general set of transformation rules for con- Z [18] is a model-oriented specification language based verting Z designs to Haskell. We considered the first on typed set theory. Since its initiation in the 1980s, Z has become increasingly popular. This popularity is problem to be relatively easy, while the second would require some ingenuity. While working on both evidenced not only by the numerous conference and 3 journal articles devoted to software development in Z, problems, we developed a collection of mappings of but also by the fact that several textbooks (e.g. [19], [20], the following form: [21] and [22] are now available on the subject. We have Z set operators —> Z sequence operators selected Z as the initial specification language, in large —> Haskell list functions part because of its widespread acceptance but, more importantly, because of its strong mathematical basis. As an example, if we consider lists without duplicate Haskell [7] is a language that closely resembles elements, set difference \ maps to range subtraction £-, Miranda, but also includes additional features such as which in turn maps to list difference \\. Given the close array comprehensions and type classes. Haskell was relationship between sequences and lists, it was often designed as a general purpose language appropriate for possible to perform a direct translation from sets to lists teaching, research, and building large systems. Although by using a modified refinement approach. Thus arose the the language is relatively new, we have chosen it as the idea of an intermediate language, which would combine implementation language because of its endorsement by features from Z and Haskell, to assist the software the functional programming community as a standard designer in translating Z specifications to Haskell for non-strict, purely functional languages. programs. FunZ and its associated methodology are the result of these early efforts. 1.2. Why an intermediate language? As far as we know, our research is the first to use an intermediate language when translating Z specifications Refinement is a well-established principle when con- to functional implementations. However, Wood and structing imperative programs from model-oriented Place [28] describe a formal development method in specifications. By refining an abstract specification to which Z specifications are initially transformed to one that is more concrete, a software developer narrows ANNotated Ada (Anna) [29] and then to Ada code. the gap between specification and implementation. In Although the transformation rules of their method are particular, the problem of proving an implementation language independent, the advantage in targeting Ada correct with respect to its specification is converted into programs is twofold: the existing specification language two smaller problems: (i) proving the concrete or lower Anna serves as the intermediate language and the Anna level specification is consistent with the abstract version; tool set simplifies much of the translation process. and (ii) verifying the code against the concrete specifica- In a similar fashion, FunZ targets Haskell, but the tion. Furthermore, by following refinement guidelines, language and associated methodology are applicable to the developer documents his or her design decisions. other functional languages by making some simple A popular method [22], successfully employed at IBM syntax changes and using the appropriate function Hursley, uses Z for specification and design and names. For instance, ++ separates the constructors of Dijkstra's guarded command language for algorithm development. An alternate approach is to translate all Z 3 A similar collection was developed for arrays.

THE COMPUTER JOURNAL, VOL.38, No. 3, 1995 FUNZ: AN INTERMEDIATE SPECIFICATION LANGUAGE 195 an algebraic datatype in Hope, whereas | is the correct that Extended ML contains only two new language Haskell syntax. As another example, — is the list difference constructs: the axiom and the place-holder ?. The operator in Miranda, while \\ is used in Haskell. minimum number of constructs that are required is By using a case study, this paper illustrates how one primarily the result of the rich module facility already can translate an abstract specification written in Z to present in SML. Haskell code via the intermediate language FunZ. Software developers may soon have the option of Furthermore, as a means of comparison, a correspond- using the two-tiered approach of Larch [10] when ing Z design is presented along with the FunZ constructing SML programs. The first draft of a Larch specification. Throughout the paper, we assume a interface language for SML, Larch/ML, appears in [37]. working knowledge of Z [18], as well as some familiarity Its designers claim that one benefit from the language is with the functional [30]. How- that it can be used to describe the semantic properties of ever, knowledge of Haskell is not required as its concepts basic data types, thus enhancing the formal semantics of are described where needed. For readers who feel an SML. Furthermore, Extended ML is currently unable to introduction to Haskell may be helpful we recommend handle references and assignments, while Larch/ML is Downloaded from https://academic.oup.com/comjnl/article/38/3/193/359139 by guest on 30 September 2021 [31] or [32]. suitable for specifying such features. The organization of the paper is as follows. The next At British Telecom Research Laboratories, con- section discusses other research that combines functional structive Z specifications have been converted into programming and formal methods. Section 3 gives a Lazy ML programs, which were used as prototypes. brief introduction to FunZ, while Section 4 contains the Due to the inefficiency of these initial programs, they actual case study. Comparisons with other work and our were then transformed into more efficient functional conclusions appear in Section 5. programs using the methodology of Burstall and Darlington [38]. A case study illustrating the technique appears in [39]. This research differs from ours in two 2. RELATED RESEARCH important ways. First, in the work of Johnson and Much of the previous work linking formal specifications Sanders, a primary goal is to obtain executable code as and functional programming has centered around soon as possible; the code then drives the design. Second, prototyping. Research has ranged from the simple the transformation of the functional program into an animation of specifications to the design of new equivalent imperative program4 is seen as part of the programming languages that integrate essential software development process. characteristics of formal methods and functional languages. 3. OVERVIEWjOF FUNZ Descriptions of how a software designer can animate The primary objective in designing FunZ was to produce specifications using Miranda appear in [33] and [19]. an intermediate specification language to assist soft- More recently, [34] discusses a mechanical translation of ware developers in transforming Z specifications to VDM specifications into Standard ML [35]. Note that, Haskell programs. Specific design constraints were as strictly speaking, Standard ML (SML) cannot be follows: classified as a purely functional language owing to its references (special values similar to the variables in an (i) The language should be a simple extension of imperative language) and its I/O facilities, neither of Haskell. which is referentially transparent. (ii) The language should be conducive to specifying the As previously mentioned, the prototyping languages characteristics of a purely functional programming me too [1] and SAMPAE [17] borrow features from language, Miranda and VDM. Compared with animation (iii) The language should preserve the notational techniques, me too forms the foundation of a complete conventions and structuring facilities of Z. software design methodology, while SAMPAE is an Furthermore, an associated methodology, patterned integral part of an interactive prototyping environment. after the Hursley method of IBM [22], was to be These languages offer the advantage that one medium is used for both specification and prototyping. However, developed simultaneously. Note that a description of SAMPAE mixes the functional and imperative the methodology encompassing FunZ appears in [40]. paradigms by including traditional control structures, To satisfy the design constraints of FunZ, features assignment statements, and updatable variables. from both Haskell and Z were integrated. The result is a specification language that looks like an extension of Another approach to software development is the Haskell, yet whose semantics parallels that of Z. In Extended ML methodology [36,12]. Extended ML is a addition, for those designers and implementors who wide-spectrum language, founded on the principles of prefer functional programming languages, FunZ allows algebraic specifications, which supports the formal software developers to model state operations more development of Standard ML (SML) programs from high-level specifications to final implementations within 4 Johnson and Sanders had not attempted this final translation a single framework. An advantage of the methodology is procedure when their paper was accepted to the 4th Z User Workshop.

THE COMPUTER JOURNAL, VOL.38, No. 3, 1995 196 L. B. SHERRELL AND D. L. CARVER

span where span where modifies ( ) inv is rel is pred is init is end span initialization part> Downloaded from https://academic.oup.com/comjnl/article/38/3/193/359139 by guest on 30 September 2021 end span FIGURE 2. Template for a FunZ operation span. As in Z, a typical operation span consists of a FIGURE 1. Template for a FunZ span. declaration part and a predicate part. Figure 2 delineates the individual components of the declaration closely to the way that they will be implemented in a final part to emphasize the differences between an operation functional program. (As one example, see the definition span and its Z counterpart. The most important change of the modifies tuple later in this section.) is in the modifies declaration, as it represents not only Similar to Z, the prominent language feature of FunZ an alteration in syntax, but also one in semantics. is the schema, albeit with a name change. To emphasize Meanwhile, the predicate part is comparable to that of the fact that these building blocks serve as a bridge Z. between Z specifications and functional programs, FunZ The modifies clause supersedes the Delta (A) con- schemas are called spans. Moreover, the graphical, box- vention of Z; all state variables that are allowed to like notation has been abandoned in favour of a syntax change must be listed explicitly. The "list" itself is known patterned after Haskell modules. as the modif ies tuple. As an example, consider the As in Z, each FunZ design consists of state and following modifies clause that forms a part of span operation spans that refine the corresponding schemas of Testok, which is described in Section 4.2: the Z specification. Unlike Z, the structure of a state span differs significantly from that of an operation span. modifies Class (ns, ts) Motivation for these differences as well as other design The declaration denotes that all the variables and decisions are described below. Note that Figure 1 predicates of spans Class6 and Class' are visible, yet contains a template for a typical state span. only the values of variables ns and ts may vary. If no FunZ requires the name of each state span to match state values should change as a result of an operation, the name of the Z schema on which it is based, thus then the modifies tuple is simply written as ( ). In other providing an automatic means of schema inclusion. Each words, the expression modif ies(Schema_Name) ( ) state span consists of four components or parts: replaces the Xi (E) convention of Z. declaration, invariant, relation, and initialization. As Another important point concerning the modif ies their respective names suggest, the declaration part clause has to do with the semantics of functional contains the necessary declarations, while the invariant programming. Recall that there is no assignment part describes the invariant on the concrete state. These statement in a purely functional language; the state two components are analogous to the declaration and must be passed around explicitly with parameters. predicate parts of the state schema in Z. Meanwhile, the Therefore, what is meant by a variable changing is that relationship between concrete and abstract states, 5 the variable must be passed as a parameter to a function commonly known as the retrieve relation, appears in and a new value must be returned as a result of this the relation part. Finally, the initialization part replaces function call. The notation of the modifies tuple is the Z schema that denotes an initial concrete state. In meant to reflect that the variables will need to be actual short, the state span groups all items associated with the parameters in a Haskell implementation. concrete state into a single specification unit. When compared to Z, this means that several declarations do 4. A CASE STUDY not have to be repeated. More importantly, it makes the design clearer to have associated parts collected into the This section traces the development of the Test same span. operation, one component of the class manager's

5 Although retrieve relation seems to be the most popular name in the 6 This span is not related to the class construct of Haskell. Although current literature, [18] uses abstraction relation, while [22] prefers class is a reserved identifier, there is no naming conflict since variable forward simulation. names are case sensitive in Haskell.

THE COMPUTER JOURNAL, VOL.38, No. 3, 1995 FUNZ: AN INTERMEDIATE SPECIFICATION LANGUAGE 197

TABLE 1. Global variables

FunZ

[Student] basic Student size: N size :: Int where size > 0 Response ::= success \ alreadytesled... data Response = Success|Alreadytested..

assistant, from an initial specification written in Z, (2) Denote any necessary constraints on the con- through a detailed design expressed in FunZ and, finally, crete objects. Place the new expressions in the to Haskell code. Our intention in selecting this standard invariant part of SS. example as a case study is to allow the reader to focus on (3) Define a retrieve relation, which maps the the development process itself, rather than the details of concrete FunZ objects to the abstract Z a complex application. objects, and place this in the relation part of Downloaded from https://academic.oup.com/comjnl/article/38/3/193/359139 by guest on 30 September 2021 SS. The mapping must be subjective as this 4.1. Requirements function will be used to translate the abstract objects of the Z specification to concrete objects The following description of the class manager's in FunZ. assistant and the Test operation are from [22]. The (4) Specify a concrete initial state in the initializa- corresponding initial Z specification can be found in tion part of SS. Add the appropriate parameters Appendix A. to the init tuple. Assistant description (C) For each Z operation schema, define a correspond- ing FunZ operation span OS. A computerized class manager's assistant is required to (1) Transfer the input and output variables to the keep track of students enrolled on a class, and to record declaration part of OS. which of them have done the midweek exercises. When a (2) Translate each predicate to an equivalent FunZ student applies for a class, he or she will be enrolled on it, expression. Install the new expressions in the unless it is full. Such a student will be presumed not to predicate part of OS. have done the exercises. When a student completes the (3) Put all state variables whose values should exercises, the fact is to be recorded. Students may leave a change into the modifies tuple of OS. class even if they have not done the exercises, but only the students who have done the exercises are entitled to a As we develop the FunZ specification, we compare the completion certificate. evolving spans to a similar design in Z. Accompanying each step is a table depicting the Z text on the abstract Test operation state, along with the corresponding text for concrete This operation records that a student has done the designs in both FunZ and Z. For the convenience of the exercises, or warns if the student is not enrolled or has reader, the definitions of all Haskell functions from the already done the exercises. FunZ specification appear in Appendix B. Finally, Appendix C contains the complete FunZ 4.2. Specification with FunZ specification for the class manager's assistant. Although we do not include the corresponding Z specification, the The process of constructing a detailed specification in reader can easily construct the respective schemas by FunZ parallels a development in Z with the primary referring to the concrete Z phrases described below. difference being that Haskell code fragments constitute a major portion of the final FunZ design. To help clarify Step A: translate global variables the overall procedure, we next present a general, methodological guideline. The developer has the option of choosing a representa- tion for any basic set, which was previously defined on (A) Translate the global variables to their FunZ the abstract state. In this case, we have decided to equivalents. postpone the decision so we merely make the appropriate (B) Define a FunZ state span SS that is equivalent to the syntax changes. Global constants and enumerated types schema representing the abstract state. are easily translated. The variables in the FunZ (1) Choose appropriate Haskell data structures or enumerated type must begin with a capital letter since user-defined types to represent the objects of the they correspond to data constructors in Haskell. abstract state. Add the necessary type declara- In the Z design, this step is not necessary because the tions to SS. global variables are already represented in the Z notation (Table 1). However, a Z designer must eventually make 7 This classic example appears frequently in the literature and was similar translations when he or she develops the program first published in [41]. code.

THE COMPUTER JOURNAL, VOL.38, No. 3, 1995 198 L. B. SHERRELL AND D. L. CARVER

TABLE 2. Objects of the state space

Z (Abstract) FunZ Z (Concrete)

enrolled, tested:P Student ts , ns : : [Student] testlist, nottested: seq Student

Step B: define a state span invariant no longer needs a predicate such as Steps B1-B4 correspond to data refinement in Z. In tested C enrolled since, by construction, the list (ns ++ other words, data structures of the target programming ts) contains each element of ts. language replace the objects in the abstract data space. In Lists ns and ts should not contain repetitions since a Z design, Z constructs must model primitive types or each list represents a group of students. This is easily ADTs of the implementation language, while a FunZ specified by using the predefined Haskell function nub, document contains actual Haskell types. Due to the which removes duplicate elements from a list. Further- expressive type system of Haskell, the software designer more, ns and ts should be disjoint since it is impossible Downloaded from https://academic.oup.com/comjnl/article/38/3/193/359139 by guest on 30 September 2021 can create high-level data types, similar in form to the for a student to have been tested and not tested at the abstract Z types, or use built in types such as lists, tuples, same time. The last predicate in the FunZ column and arrays. designates this final requirement. Symbols ==, &&, 'elem', and 'notElem' are infix Step Bl: choose Haskell data structures to represent operators that correspond to the =, A, G, and ^ of Z. In abstract objects FunZ, Haskell operators are used in predicates, while the logic operators of Z are reserved for combining spans. Although the sets in a model-oriented specification can The reason for using Haskell in each of the predicates is be implemented by means of an abstract data type [42], that some software developers may want to implement we base our design on the Haskell list and its associated the invariant. Even when the state invariant is not list functions. In particular, the set of enrolled students is executed, describing the constraints in Haskell helps the represented by a list of students who have completed the developer to understand the chosen data structure better. exercises (ts) and a list of students who have not (ns). As a final note, the keyword implies is not a part of Because the arrangement of students in each list is Haskell. This boolean-valued function has been added to unimportant, the additional ordering information FunZ to handle implication, because => is a reserved offered by lists as compared to sets can be disregarded. operator in Haskell. Furthermore, in this example, there is no need to worry An important distinction about Haskell's equality about removing duplicate elements after a list insertion operator is that it is one of the methods defined on the since a student is only added to the group of tested type class Eq. The operator can only be applied to objects students if he or she is not already a member. of the same type, and the corresponding type must be an Meanwhile, in the Z design (see Table 2), sequences instance of Eq. Since the list data structure is a predefined model the Haskell lists. This is a good match as many of instance of the equality class, the FunZ expressions in the sequence operators from the Z Mathematical Tool- Table 3 are also legal in Haskell. kit [18] correspond to basic list functions. The concrete Z and FunZ invariants are quite similar. With respect to the first predicate, sequence operators # Step B2: place necessary constraints on the concrete and " correspond to the predefined Haskell functions objects length and (++). Since sequences are partial functions, Next, we give an informal description of the FunZ the range (ran) operator can be used to express the expressions that will form the invariant part of the state fact that these particular sequences do not contain span Class (see Table 3). Since the concatenation ++ of repetitions. In other words, the length (#) of each lists ns and ts corresponds to the set of enrolled students, sequence should equal the number of elements in its its length cannot exceed the maximum size of the class. range. An alternate way of specifying this information Unlike the invariant on the abstract state, the concrete would have been to declare sequences nottested and

TABLE 3. Invariants on the state space

Z (Abstract) FunZ Z (Concrete)

# enrolled^size length (ns++ts) ^ size # (nottested" testlist) < size tested C enrolled ns == nub ns # not tested = # ran nottested ts == nub ts # testlist = # ran testlist (s 'elem' ns) implies ran nottested n ran testlist = 0 (s 'notElem' ts) kk (s 'elem' ts) implies (s 'notElem' ns)

THE COMPUTER JOURNAL, VOL. 38, No. 3, 1995 FUNZ: AN INTERMEDIATE SPECIFICATION LANGUAGE 199

TABLE 4. Retrieve relations TABLE 6. Input and output variables

FunZ z FunZ abmap : : [Student] - > P Student sV Student s : : in Student enrolled = set (ns + + ts) enrolled = ran (testlist ~ nottested) r\: Response r : : out Response tested = set ts tested = ran lestlist

Step C: define operation spans testlist as injective sequences with the Z notation iseq in step Bl. The final predicate expresses the fact that the Observe that this step denotes an iterative process. Here, two sets of students are disjoint. we only describe the construction of an operation span for the successful component of the Test operation, Step B3: define a retrieve relation namely Testok, since the spans for the error conditions

are relatively straightforward. However, the definitions Downloaded from https://academic.oup.com/comjnl/article/38/3/193/359139 by guest on 30 September 2021 Designing a retrieve relation in FunZ parallels the for all the operation spans are included in Appendix C. activity in Z. In this case, the retrieve relation is a total In particular, the definition for span Test is simply the function because each abstract object can be obtained by means of the function set, which converts list of disjunction of spans Testok, AlreadyTested, and type a to sets of type P a. The definition of set NotEnrolled. follows: Step Cl: translate the input and output variables :: [a] — > pa set When transferring the input and output variables to set[] ={} the FunZ span, only a slight change in syntax is set(x:xs) = {x}U set xs required (Table 6). Double colons replace the single colons of Z to match the typing declarations in In the Z design, the retrieve relation is a mapping from Haskell. In addition, keywords in and out are used sequences of students to powersets of students (Table 4). to indicate input and output variables, since the However, the Z document does not contain an explicit standard Z suffixes ? and ! are not allowed in Haskell declaration for the type of the mapping. As in the FunZ identifiers; Meanwhile, in Z the variables are simply design, the relation is a total function. In particular, each copied from the abstract schema to the concrete set of students can be obtained by applying the range one. operator of Z to the appropriate sequence.

Step B4: specify a concrete initial state Step C2: translate the predicate part In FunZ, the initialization part consists of two tuples. To obtain predicates on the concrete state, one uses the The first contains the variables to be initialized and the retrieve relation (see step B3) as a guide. Each abstract second contains the actual values. The notation reflects object in the Z operation schema is replaced with its the fact that the initial values for the concrete objects concrete representation. By using the properties of set must be passed as actual parameters when the first theory and theorems provided with FunZ, one then operation of a system is executed. For the class attempts to simplify the resulting expressions. The manager's assistant, there should be no students in the strategy is to obtain expressions where Z operators class when the system is first activated. Therefore, the map to Haskell functions. first tuple contains formal parameters ns and ts, while To help clarify the subsequent translation, Table 7 the second specifies both actual arguments as the empty contains the transformation rules for this example. The list. first three rules specify syntax changes for input and In Z, empty sequences are used to denote the output variables as well as enumerated types, whereas corresponding empty lists. The difference in the two rules 4 and 5 relate set membership symbols to approaches is that the FunZ specification always Haskell operators. Finally, rule 6 requires that list xs contains two tuples, while the Z design will contain n contain no duplicates in order for the transformation terms, where n is the number of variables to be initialized to hold. (Table 5). A description of the translation process for each of the predicates from schema Testok (see Appendix A or column one of Table 8) follows. Beginning with the TABLE 5. Initial states first abstract predicate, the derivation of a concrete z FunZ Z equivalent is: (Abstract) (Concrete) si € enrolled =*• enrolled' = 0 (ns, ts) nottested' = ( ) s? € set (ns + + ts) =>• retrieve function tested' = 0 testlist' = ( > s 'elem' (ns + + ts) rules 1, 4, and 6

THE COMPUTER JOURNAL, VOL.38, No. 3, 1995 200 L. B. SHERRELL AND D. L. CARVER

TABLE 7. Transformation rules informal argument that assumes the previous concrete predicates and the invariant. Rules Z FunZjHaskell (s 'elem' ns implies s 'notElem' ts) 1 varnamel varname 2 varname\ varname && (s 'elem' ts implies s 'notElem' ns) 3 enumid Enumid 4 e 'elem' from span Class. An intuitive idea of the reasoning is as 5 'notElem' follows: after student s is inserted at the front of list ts, s 6 set xs xs must be removed from ns to preserve the invariant. Note that \\ is the Haskell operator for list difference. In particular, the expression xs \\ ys returns the list xs Similarly, the second predicate translates as: with only the first occurrence (if any) of each element in s? $ tested => ys removed. Therefore, ns \\ [s] has the desired effect of

removing student s from ns, the group of non-tested Downloaded from https://academic.oup.com/comjnl/article/38/3/193/359139 by guest on 30 September 2021 s? ^ set ts => retrieve function students. s 'notElem' ts rules 1, 5 and 6 Finally, to derive a concrete equivalent of the last By jointly considering the above results, an additional abstract predicate, the output response, one simply simplification is possible. Observe that student s is a applies rules 2 and 3. In other words, the designer member of the concatenation of lists ns and ts, but is not drops the explanation point from the output variable and contained in ts. Therefore, s must be an element of ns replaces the enumerated type value in Z with its or, in FunZ, s 'elem' ns. Since this new, simpler corresponding Haskell data constructor. predicate implies Note that span Test ok (see Appendix C) does not include both the predicates s 'elem' ns and s s 'elem' (ns + + ts) 'notElem' ts in its predicate part. Only the first predicate appears, since the second can be derived from we select it as the first predicate on the concrete state. the first and the invariant on span Class. Continuing in the same fashion, the derivation steps Meanwhile, to translate the abstract predicates to for the third concrete predicate are: concrete predicates in Z, one follows a similar approach tested' — tested U {s7 to that described above. In particular, the retrieve function (see the Z predicates in step B3) serves as a set ts' = set ts U {s?} retrieve function (twice) translator for the objects on the abstract state. Rather set ts' = {s?} U set ts commutativity of U than present the derivation steps, we simply include the set ts' = set (s?:ts) => definition of set final predicates in Table 8. Note that the removal of ts = s:ts rules 6 (twice) and 1 student s? from the set of nottested students is denoted by the range subtraction operator &•. Note that the commutative law was applied so that the As a finalcomment , although the translation processes new student would be added to the front of the list, an in Z and FunZ are very similar, there are two major O(l) operation, rather than the end of the list, which differences in the resulting designs. First, predicates such requires O(n) time. Furthermore, the substitution of list as id_name = id_name can appear in the Z schemas. In (s: ts) for set (s: ts) was valid because student s is not FunZ, these predicates are deleted due to the semantics an element of ts according to the second concrete of the modifies tuple. (Recall the discussion from predicate. Section 3). The other difference is that the designer Now consider the fourth abstract predicate. Applying who uses FunZ as opposed to Z has a design the retrieve relation twice, produces the result: document with Haskell code fragments after the completion of this step. set (ns' + + ts') = set (ns + + ts)

An equivalent concrete predicate can be obtained by Step C3: construct the modifies tuple applying laws of set theory and various theorems To determine which variables should be placed in the provided with FunZ. However, we present a more modif ies tuple, the designer checks the predicates

TABLE 8. Predicates for the successful component of the Test operation

Z (Abstract) FunZ Z (Concrete)

5? 6 enrolled s 'elem' ns s"> e ran nottested 5? £ tested s 'notElem' ts s"> £ ran testlist tested' = {s?} U tested ts'= s:ts testlist' = (s?)" testlist enrolled' = enrolled ns' = ns \ \ [s] nottested' = nottested'•&• {s?} r\ = success r = Success r! = success

THE COMPUTER JOURNAL, VOL.38, No. 3, 1995 FUNZ: AN INTERMEDIATE SPECIFICATION LANGUAGE 201 obtained in the previous step for decorated variables. In that could terminate as a consequence of the correspond- the case of Testok, the relevant predicates are as follows: ing abstract operation. The respective proof obligation is ns' — ns \\ [s] and ts' = s: ts. Therefore, the modifies as follows: clause for concrete schema Testok is: VAAstate; AStSpan; x :: inp X; y : : out Y • modifies Class (ns, ts) pre Aop A AStSpan \ init A OpSpan => Aop Meanwhile, in the Z design, this step consists of a simple translation. In particular, instead of constructing The safety and liveness conditions of FunZ reflect the a modifies clause, the designer translates all schema fact that a state span contains two additional com- names included in the abstract operation schema to their ponents when compared to a state schema. In particular, respective names on the concrete state. the subterm StSpan\init tells the designer to disregard This completes the last step in the guidelines for the initialization part, as the proofs for safety and translating an abstract specification written in Z to a liveness do not depend on any of the initialization more concrete one expressed in FunZ. However, for predicates. Furthermore, as in the proof obligation for Downloaded from https://academic.oup.com/comjnl/article/38/3/193/359139 by guest on 30 September 2021 those designers who wish to prove that the resulting initial states, these conditions do not explicitly mention FunZ design is a correct refinement of the original Z the retrieve function. Note that the FunZ proof specification, several proof obligations must be met, as obligations use the A symbol to denote before and discussed in the next section. after state schemas, as well as state spans. In conclusion, the proof obligations for the initial 4.3. Proof obligations states and test operation from the class manager's assistant follow. Here we simply list the required The proof obligations in FunZ are analogous to those of conditions, while the actual proofs appear in [40]. Z. However, because the retrieve relation for the class manager's assistant is a function (see Section 4.2, step Class; Class • Class: init' => Classinit' B3), the comments below are limited to functional Class; Class; s:: inp Student • pre Test A Class \init =*• pre Test refinement [18]. In particular, the discussion includes a VAClass; AClass; s:: inp Student; r:: out Response • brief overview of the proof obligations in a generic pre Test A AClass\init A TestSpan =>• Test framework, followed by the conditions specific to this case study. A single proof obligation must be fulfilled to show that 4.4. Haskell code every concrete initial state corresponds to an abstract The class manager's assistant is a suitable candidate for initial state. In FunZ, this concrete is stated as follows: an abstract data type since it consists of a datatype V Astate; StSpan • StSpan: init' => Ainit' corresponding to the classroll and an associated set of operations which act on this type. In Haskell, each ADT Note that Astate and Ainit represent the schemas is represented by a module. A skeleton of the module denoting the abstract state space and the abstract initial that implements the class manager's assistant follows. state. Moreover, the notation StSpan: init' designates the concrete state after initialization. This means that the module ClassADT (Classroll, enroll, test, leave, enquire) where actual parameters of the corresponding init tuple import BasicDef type Classroll = (Nottested, Tested) replace the formal parameters when the system first type Nottested = [Student] becomes operational. Although the above proof type Tested = [Student] obligation does not explicitly mention the retrieve enroll :: Classroll ->Student -> (Classroll, Response) function, its equations are visible due to the declaration Definition of enroll would appear here of StSpan. test :: Classroll -> Student -> (Classroll, Response) Definition of test (described below) In addition to the condition relating initial states, leave :: Classroll -> Student -> (Classroll, Response) functional refinement requires that every operation span Definition of leave would appear here satisfy two proof obligations. These obligations are enquire :: Classroll -> Student-> (Classroll, Response) known as the safety and liveness conditions [22]. The Definition of enquire would appear here safety condition ensures that whenever an operation on Module ClassADT exports the type Classroll and its the abstract state {Aop) terminates, its corresponding associated operations: enroll, test, leave, and operation on the concrete state (OpSpan) will also enquire. As is customary for an ADT, the representa- terminate. This is expressed by tion of the type and the implementation of its operations VAstate; StSpan; x : : inp X • pre Aop are hidden from the user. The module does not contain A StSpan\init =>• pre OpSpan definitions for the Student and Response types, as we are assuming that the module BasicDef, which appears Meanwhile, the liveness condition guarantees that the in the import declaration, contains these definitions. concrete state resulting from a concrete operation Note that type Classroll could simply be defined as represents a valid abstract state or, in other words, one ([Student] , [Student]). However, we introduce the

THE COMPUTER JOURNAL, VOL.38, No. 3, 1995 202 L. B. SHERRELL AND D. L. CARVER

TABLE 9. Preconditions and postconditions for Test spans text of a FunZ document looks like extended Haskell code, whereas the development process itself emulates Span Precondition Postcondition that of Z. In particular, FunZ preserves the features of Z

Testok s 'elem' ns ts = s:ts that contribute to the incremental development of ns' = ns \\ [s] specifications by maintaining the ideas of the schema r = Success calculus and schema inclusion. Furthermore, FunZ AlreadyTested s 'elem' ts r = Alreadytested communicates the characteristics of a purely functional to an implementor through NotEnrolled s 'notElem' ns r = Notenrolled special language constructs such as the modifies and s 'notElem' ts init tuples. In this paper, we gave a general overview of the FunZ type synonyms Nottested and Tested for better notation and used a case study to illustrate how one can readability. translate Z specifications to Haskell code. As a means of We now translate the FunZ specification for the Test comparison, a corresponding Z design was developed Downloaded from https://academic.oup.com/comjnl/article/38/3/193/359139 by guest on 30 September 2021 operation into a corresponding Haskell function. Recall simultaneously. We now summarize the differences the definition of Test: between Z and FunZ as design languages by explaining Test=Testok VAlreadyTested VNotEnrolled how the usage of FunZ affects its two types of users: specifiers and implementors. The disjunction of spans indicates that a case analysis is The major difference to the specifier/designer who uses in order. To help clarify the analysis, Table 9 contains the FunZ has to do with the construction of the predicates pre- and post-conditions for each component of the on the concrete state. As illustrated in this paper, the operation. expressions in a FunZ design are sometimes more Note that the single precondition s 'notElem' complex (e.g. see the invariants in Table 3). However, (ns + 4- ts) from span NotEnrolled has been replaced the advantage gained in applying FunZ is that the by two equivalent preconditions. By recalling the designer is better able to describe certain aspects of the predicate system, those unique to functional languages, since FunZ (s 'elem' ns implies s 'notElem' ts) is expressly designed for this purpose. && (s 'elem' ts implies s 'notElem' ns) The major difference to the implementor/programmer who works from a FunZ specification is that he or she from the state invariant of span Class (step B2 in actually begins with a skeleton of an implementation Section 4.2), it is clear that the preconditions for each Moreover, if the FunZ document includes formal proofs, component are mutually exclusive. Therefore, the the programmer has an even better understanding of the following implementation of the test function software design as it applies to Haskell. The overall effect employs a sequence of guards. is that the distance, and therefore, the time, from design test : : Classroll —» Student —> (Classroll, Response) to code is reduced. test (ns, ts) s | s 'elem' ns = ((ns\\ [s], s:ts), Success) Likewise, when comparing FunZ with traditional | s 'elem' ts = ((ns, ts), Alreadytested) animation techniques [33], [19] and [43], two properties | otherwise = ((ns, ts, Notenrolled) distinguish the approach encompassing FunZ: (i) the FunZ document serves as a record of the design process; The semantics of pattern matching indicate that the and (ii) the user may prove the final implementation guards will be evaluated top to bottom until one returns correct with respect to its initial specification. Further- the value True. In this case, if both the first and more, prototyping is still feasible within the framework second guards should fail, then the precondition of of FunZ since code fragments are obtained relatively NotEnrolled is guaranteed. To avoid the unnecessary early in the process. A user may, in fact, provide the evaluation of predicates s 'notElem' ns and s customer with a working prototype before satisfying any 'notElem' ts, the expression otherwise comprises the proof obligations. last guard. Note that otherwise is simply syntactic sugar Finally, the intermediate specification language FunZ for the Boolean value True. and its associated methodology offer several advantages It is easy to see that the function above is a realization to software developers who wish to translate their Z of its FunZ specification. In addition to the guards specifications to functional programs. First, the corresponding to the preconditions, notice that the first specification language integrates features from Z with argument of test corresponds to the modifies tuple of those of the functional programming paradigm to span Testok (step C3 in Section 4.2). provide a bridge between Z specifications and functional implementations. At the same time, the methodology 5. CONCLUSIONS provides a framework for recording design decisions, We have defined an intermediate specification language, which is useful for future maintenance. Within this named FunZ, that can be used to produce purely framework, the user may select a development procedure functional programs from Z specifications. The formal ranging from an intuitive style, similar to that presented

THE COMPUTER JOURNAL, VOL.38, No. 3, 1995 FUNZ: AN INTERMEDIATE SPECIFICATION LANGUAGE 203 in this paper, to a fully formal approach as discussed in [18] Spivey, J. M. (1989). The Z Notation: A Reference [40]. In conclusion, FunZ is an attractive software Manual. Prentice Hall, New York. development method for both designers and implementors [19] Diller, A. (1990) Z. An Introduction to Formal Methods. John Wiley, Chichester. who prefer purely functional programming languages. [20] Potter, B., Sinclair, J. and Till, D. (1991) An Introduction to and Z. Prentice Hall, Englewood REFERENCES Cliffs, NJ. [21 ] Ince, D. C. (1992) An Introduction to Discrete Mathematics, [1] Henderson, P. (1986) Functional programming, formal Specification, and Z. Clarendon Press, specification, and rapid prototyping. IEEE Trans. Oxford. Software Engineering, 12, no. 2, 241-250. [22] Wordsworth, J. B. (1992) Software Development with Z: A [2] Hekmatpour, S. and Ince, D. (1988) Software Practical Approach to Formal Methods in Software Prototyping, Formal Methods, and VDM. Addison- Engineering. Addison-Wesley, Wokingham. Wesley, Wokingham. [23] Morgan, C. C. (1990) Programming from Specifications. [3] Joosten, S. M. M. (1989) The use of functional Prentice-Hall, New York.

programming in software development. Ph.D. Thesis, [24] King, S. (1990a) Z and the refinement calculus. In VDM Downloaded from https://academic.oup.com/comjnl/article/38/3/193/359139 by guest on 30 September 2021 University of Twente, Enschede, the Netherlands. '90: VDM and Z-Formal Methods in Software Develop- [4] Hazan, J. E., Jarvis, S. A., Morgan, R. G. and Garigliano, ment, Third International Symposium of VDM Europe, R. (1993) Understanding Lolita: program comprehension Kiel, FRG, Springer-Verlag LNCS 428, pp. 164-188. in functional languages. In Proceedings of IEEE Second [25] King, S. (1990b) A refinement calculus case study. In Workshop on Program Comprehension, Capri, Italy. IEEE Report PRG-TR-7-90, Oxford University Computing Computer Society Press, Los Alamitos, CA, pp. 26-34. Laboratory, Oxford. [5] Turner, D. (1990) An overview of Miranda. In Turner, D. [26] Sherrell, L. B. and Carver, D. L. (1993) Z meets Haskell: a (ed.), Research Topics in Functional Programming. case study. In Proceedings of the Seventeenth Annual Addison-Wesley, Reading, MA. International Computer Software and Applications [6] Srivas, M. and Bickford, M. (1992) Moving formal Conference, Phoenix, AZ. IEEE Computer Society methods into practice: verifying the FTPP Scoreboard: Press, Los Alamitos, CA, pp. 320-326. phase 1 results. NASA Contractor Report 189607, [27] Sherrell, L. B. and Carver, D. L. (1994) Experiences in Langley Research Center, Hampton VA. translating Z designs to Haskell implementations. [7] Hudak, P., Peyton-Jones, S. and Wadler, P. (1992) Report Software—Practice and Experience, 24, no. 12, 1159-1178. on the programming language Haskell, a nonstrict, purely [28] Wood, W. G. and Place, P. R. H. (1991) Formal functional language. SIGPLAN Notices, 27, no. 5. development of Ada programs using Z and Anna: a case [8] Goblirsch, D. M. (1994) A software system for training study. In Report SEI-91-TR-1, Software Engineering phonetic hidden Markov models. Version 2.0 (Draft) Institute, Pittsburgh, PA. Available from anonymous ftp at nebula.cs.yale.edu. [29] Luckham, D. C, von Henke, F. W., Krieg-Bruchener, B. [9] Giegerich, R. and Hughes, J. (1994) Functional and Owe, O. (1987) ANNA: A Language for Annotating programming in the real world. Dagsthul-Seminar- Ada Programs. Springer-Verlag LNCS 260. Report, 89, 16.05-20.05.94 (9420). [30] Bird, R. and Wadler, P. (1988) Introduction to Functional [10] Guttag, J. V., Horning, J. J. and Wing, J. M. (1985) The Programming. Prentice Hall, New York. Larch family of specification languages. IEEE Software, [31] Hudak, P. and Fasel, J. H. (1992) A gentle introduction to 2, no. 5, 24-36. Haskell. SIGPLAN Notices, 27, no. 5, T1-T53. [11] Feijs, L. M. G. and Jonkers, H. B. M. (1992) Formal [32] Davie, A. J. T. (1992) An Introduction to Functional Specification and Design. Cambridge University Press, Programming Systems Using Haskell. Cambridge Cambridge. University Press, Cambridge. [12] Sannella, D. and Tarlecki, A. (1991) Extended ML: Past, [33] O'Neill, G. (1989) Rapid prototyping of formal present, and future. In Proceedings of the 7th Workshop on specifications using Miranda. In NPL Report DITC Specification of Abstract Data Types, Wusterhausen/Dosse, 150/89, National Physical Laboratory, Teddington, Germany. Springer Verlag LNCS 534, pp. 297-322. Middlesex, UK. [13] Carrington, D., Duke, D., Duke, R., King, P., Rose, G. [34] O'Neill, G. (1992) Automatic translation of VDM and Smith, G. (1989) Object-Z: an object-oriented specifications into Standard ML programs. Comp. J., extension to Z. In Formal Description Techniques 35, 623-624. {FORTE '89), North Holland, pp. 281-296. [35] Milner, R., Tofte, M. and Harper, R. (1990) The [14] Schuman, S. A. and Pitt, D. H. (1987) Object-oriented Definition of Standard ML. MIT Press, Cambridge, MA. subsystem specification. In L. G. L. T. Meertens (ed), [36] Sannella, D. (1990) Formal program development in Program Specification and Transformation. Elsevier Extended ML for the working programmer. In Morgan, Science Publishers B.V., North-Holland, pp. 313-341. C. and Woodcock, J. C. P. (eds), 3rd Refinement [15] Burstall, R. M., MacQueen, D. B. and Sannella, D. T. Workshop, Hursley Park, UK. Springer-Verlag, London, (1980) Hope: an experimental applicative language. In pp. 99-130. The 1980 LISP Conference, Stanford University, [37] Zaremski, A. M., Rollins, E. and Wing, J. M. (1992) University of Santa Clara, The USP Co. Thoughts on a Larch/ML and a new application for LP. [16] Burstall, R. M. and Goguen, J. A. (1977) Putting theories In Report CMU-CS-92-135, Carnegie Mellon University, together to make specifications. In Proceedings of the 5th Pittsburgh, PA. International Joint Conference on Artificial Intelligence, [38] Burstall, R. M. and Darlington, J. (1977) A transforma- Cambridge, MA, pp. 1045-1058. tion system for developing recursive programs. Journal of [17] Henhapl, W., Kaes, S. and Snelting, G. (1991) Utilizing the ACM, 24, no. 1,44-67. fifth generation technology in software development [39] Johnson, M. and Sanders, P. (1990) From Z specifications tools. In Software Development Environments and CASE to functional implementations. In Proceedings of the Technology, European Symposium, Konigswinter, Fourth Annual Z User Meeting, Oxford. Springer-Verlag, Germany. Springer-Verlag LNCS 509, pp. 151-166. London, pp. 86-112.

THE COMPUTER JOURNAL, VOL. 38, No. 3, 1995 204 L. B. SHERRELL AND D. L. CARVER

[40] Sherrell, L. B. (1995) A formal methodology for deriving represents the case when the following two conditions purely functional programs from Z specifications via the hold: (i) a user enters an input student si who has been intermediate specification language FunZ. Software Engineering Group, Louisiana State University, PhD tested or, in other words, completed the exercises; and (ii) dissertation. the database contains no record that this student has [41] Jones, C. B. (1980) Software Development: A Rigorous been tested. After student si is added to the set of tested Approach. Prentice-Hall, Englewood Cliffs, N.J. students, the success response should be generated. [42] North, N. D. (1990) An implementation of sets and maps as Miranda abstract data types. In NPL Report DITC Testok 162/90, National Physical Laboratory, Teddington, Middlesex, UK. AClass [43] Goodman, H. S. (1993). Animating Z specifications in si : Student; r\ : Response Haskell using a monad. Available from anonymous ftp at ftp.cs.bham.ac.uk. si £ enrolled

APPENDIX A si g tested Downloaded from https://academic.oup.com/comjnl/article/38/3/193/359139 by guest on 30 September 2021 The initial Z specification for the class manager's tested' = tested U {si} assistant follows. All schemas are from [22]. enrolled' = enrolled r\ = success The abstract state Schema AlreadyTested represents an error condition: To describe the class manager's assistant, we need three the user enters a student si who has previously been global variables in addition to the names of schemas. recorded as completing the exercises. The appropriate Since we are uninterested in the representation of a output response is already tested. student, we use a given set to introduce the type Student. A Iready Tested [Student] "EClass si : Student; r\ : Response A system user will be required to specify the maximum size of a class, so the variable size is declared. si e tested | size : N r\ = alreadytested An enumerated type Response is defined in order that Schema NotEnrolled also designates an error condi- appropriate warnings or messages can be delivered at the tion. In this case, the user enters student si who is not a conclusion of an operation. member of the class. The corresponding output response is notenrolled. Response ::= success \ already tested \ notenrolled... NotEnrolled. The abstract state for the class manager's assistant is defined in schema Class. The class roll is represented by EC lass set enrolled, while the set of students who have completed si : Student; r\ : Response the exercises is designated by tested. si g enrolled Class r\ = notenrolled enrolled, tested: P Student Finally, the disjunction of the previous schemas ^enrolled < size comprises the definition of operation Test. tested C enrolled Test = Testok V AlreadyTested V NotEnrolled When the class manager's assistant is first activated, no students will be enrolled. The schema representing the APPENDIX B abstract initial state follows. The following function definitions, along with their Classlnit = [Class' | enrolled1 = 0] comments, are adapted from the Standard Prelude as Notice that there is no need for a predicate stating that published in the Haskell Report [7]. Note that the symbol tested is initially empty. This fact can be derived from ., which appears in several definitions, is the Haskell infix above since the tested students are a subset of the operator for function composition. Also / =, which is enrolled students. defined in class Eq, is the symbol for inequality. list concatenation (right-associative) Schemas for Test (++) :: [a] - [a] - [a] Schema Testok specifies the successful recording of a xs + + ys = f oldr ( : ) ys xs student who has finished the exercises. In particular, it

T.HE COMPUTER JOURNAL, VOL. 38, No. 3, 1995 FUNZ: AN INTERMEDIATE SPECIFICATION LANGUAGE 205 foldr, applied to a binary operator, a -— Boolean function for disjunction starting value (typically the right- (||) :: Bool- > Bool- > Bool identity of the operator), and a list, True || _ = True reduces the list using the binary operator, from right to left: False || x = x foldr f z [xl, x2,...,xn]==xl 'f (x2 'f -— elem is the list membership predicate, (...(xn'f'z)...)) — usually written in infix form, foldr :: (a-»b-»b) ->b-* [a] -»b — e.g., x 'elem' xs. foldr f z [ ] = z elem :: (Eq a) => a- > [a]- > Bool foldr f z(x:xs) = f x (foldr f z xs) elem = any . (==) length returns the length of a f inite list as -— notElem is the negation of predicate elem. an Int; it is an instance of the more general genericLength, the result type of which may be notElem :: (Eq a) => a- > [a]- > Bool Downloaded from https://academic.oup.com/comjnl/article/38/3/193/359139 by guest on 30 September 2021 any kind of number. notElem = all . (/=) genericLength :: (Numa)=>[b] -> a -— Applied to a predicate and a list, any genericLength = foldl (\n_-> n + l) 0 determines if any element — of the list satisfies the predicate. length :: [a] - > Int any :: (a- > Bool)— > [a]— > Bool length = genericLength any p = or . map p foldl is the left-to-right dual of foldr. — map f xs applies f to each element of xs; i.e., foldl :: (a->b->a)->a->[b]->a — map f xs == [f x | x *— xs] . foldl f z [ ] = z map :: (a- > b)- > [a]- > [b] foldl f z (x:xs) = foldl f (f z x) xs) map f [ ] = [ ] equality class map f (x:xs) = f x : map f xs class Eq a where — or returns the disjunction of a Boolean list. (==), (/ =) - > a- > Bool :: a — For the result to be False, the list must be x / = y = not (x == y) finite; True, however, results from a True Boolean function for negation value at a f inite index of a f inite or inf inite list. not :: Bool- > Bool or :: [Bool]— > Bool not True = False or = foldr (||) False not False = True -— and is the conjective dual of or. nub (meaning "essence") removes duplicate elements from its list argument and :: [Bool]— > Bool nub :: (Eq a)=> [a]=> [a] and = foldr (&&) True nub(] = [] -— list difference (non-associative). In the nub (x:xs) = x:nub (filter (/=x)xs) -— result of xs\\ ys, the — first occurrence of each element of ys in turn filter, applied to a predicate and a list, (if any) has been removed from xs. Thus, returns the list of those elements that (xs + + ys) \ \xs == ys. satisfy the predicate; i.e. ; (\\) :: (Eq a) => [a]-> [a]-> [a] f ilter p xs == [x|x <— xs, p x]. (\\) = foldl del filter :: (a- > Bool) - > [a] - > [a] — del takes a list and an element and returns an filter p = foldr (\x xs — > if p x -— identical list except the first occurrence of then x:xs else xs) [ ] the specified element is removed. Boolean function for conjunction del : (Eqa)=>[a]->a->[a] (&&) :: Bool - > Bool - > Bool del[]_ =[] True && x = x del (x:xs) y |x == y =xs False && _ = False | otherwise = x : xs 'del' y

THE COMPUTER JOURNAL, VOL.38, No. 3, 1995 206 L. B. SHERRELL AND D. L. CARVER

APPENDIX C pred is s'elem' ns The following design spans are based on the schemas in ts' = s:ts Appendix A. For additional details concerning spans ns' = ns \ \[s] Class and Testok see Section 4.2. s = Success end span Testok Span Class Span AlreadyTested span Class where span AlreadyTested where ts :: [Student] modifies Class ( ) ns :: [Student] s : : in Student inv is r : : out Response Downloaded from https://academic.oup.com/comjnl/article/38/3/193/359139 by guest on 30 September 2021 length (ns + +ts) ^ size pred is (ns == nubns)&&(ts == nub ts) Vs :: Student • (s 'elem' ns implies s 'notElem' ts) s 'elem' ts Vs :: Student* (s 'elem' ts implies s 'notElem' ns) r = Alreadytested end span AlreadyTested rel is abmap :: [Student]— > P Student Span NotEnrolled tested = set ts enrolled — set (ns ++ ts) span NotEnrolled where modif ies Class ( ) init is s : : in Student (ns, ts) r : : out Response ([],[]) end span Class pred is s 'notElem' (ns ++ ts) r = Notenrolled Span Testok end span NotEnrolled span Testok where modifies Class (ns, ts) Span Test s : : in Student span Test where r : : out Response Test = Testok V AlreadyTested VNotEnrolled end span Test

THE COMPUTER JOURNAL, VOL. 38, No. 3, 1995