Why Nominal-Typing Matters in Mainstream

Total Page:16

File Type:pdf, Size:1020Kb

Why Nominal-Typing Matters in Mainstream Why Nominal-Typing Matters in Object-Oriented Programming Moez A. AbdelGawad College of Mathematics and Econometrics, Hunan University Changsha 410082, Hunan, P.R. China Informatics Research Institute, SRTA-City New Borg ElArab, Alexandria, Egypt [email protected] January 1, 2018 Abstract type systems. Recently, a domain-theoretic model of nominally-typed OOP was compared to well-known The statements ‘inheritance is not subtyping’ and models of structurally-typed OOP. Combined, these ‘mainstream OO languages unnecessarily place re- comparisons provide both a clear technical account strictions over inheritance’ have rippled as mantras and a deep mathematical account of the relation be- through the PL research community for years. Many tween nominal and structural OO type systems that mainstream OO developers and OO language design- have not been presented before, and they help demon- ers, however, do not accept these statements. In strate the key value of nominal typing and nominal nominally-typed OO languages that these developers subtyping to OO developers and language designers. and language designers are dearly familiar with, in- We believe a clearer understanding of the key se- heritance simply is subtyping; and they believe OO mantic advantage of pure nominal OO typing over type inheritance is an inherently nominal notion, not pure structural OO typing can help remedy the ex- a structural one. isting schism. We believe future foundational OO Nominally-typed OO languages, such as Java, C#, PL research, to further its relevance to mainstream C++, and Scala, are among the most used program- OOP, should be based less on structural models of OOP and more on nominal ones instead. arXiv:1606.03809v3 [cs.PL] 29 Dec 2017 ming languages today. However, the value of nominal typing to mainstream OO developers, as a means for designing robust OO software, seems to be in wait for full appreciation among PL researchers—thereby per- 1 Introduction petuating an unnecessary schism between many OO developers and language designers and many OO PL In 1990, Cook et al. shocked the programming lan- researchers, with each side discounting, if not even guages (PL) research community by declaring that, disregarding, the views of the other. in object-oriented programming, ‘inheritance is not In this essay we strengthen and complement earlier subtyping,’ meaning there is no one-to-one corre- efforts to demonstrate the semantic value of nomi- spondence between type inheritance and subtyping nal typing by presenting a technical comparison be- in OO programming languages, further adding that tween nominal OO type systems and structural OO mainstream OO languages unnecessarily ‘place re- 1 strictions over inheritance.’ Over the years, these and interface names and trait names in OO languages statements rippled, as mantras, through the PL re- that support these notions—are used as type names search community. in nominally-typed OO languages. Class—and inter- To this day, however, many mainstream OO de- face and trait—behavioral contracts, typically writ- velopers and OO language designers cannot digest or ten informally in code documentation comments, are accept not identifying type inheritance with subtyp- specifications of the behavioral design intentions of ing. Simply, the statement of Cook et al. is not true OO software developers. In nominally-typed OOP, a in nominally-typed OO languages that these develop- reference to a class (or interface or trait) name is in- ers and language designers are dearly familiar with. variably considered a reference to the associated con- Further, they see that the so-called “restriction” of tract too. Given this association of type names to type inheritance in nominally-typed OO languages is corresponding behavioral contracts, nominal typing strongly justified, or, more so, that a structural view allows associating types of objects with (formal or in- of inheritance is in fact an unjustified redefinition of formal) behavioral contracts. type inheritance, which they view as an inherently By using type names in their code, OO develop- nominal notion. ers using nominally-typed OO languages have a sim- Nominally-typed OO languages are among the ple way to refer to the corresponding contracts— top most-used programming languages today. Ex- referring to them as richer specifications of object amples of nominally-typed OO languages include state and behavior that can be checked statically and many industrial-strength mainstream OO program- that can be used during runtime. This readily access ming languages such as Java [44], C# [1], C++ [2], to richer object specifications—which cannot be ex- and Scala [61]. Nominally-typed OO languages have pressed in a natural way using non-nominal (a.k.a., remained among the top most-used programming structural) record types that, by definition, include languages for over a decade [14, 5]. And, even by the no class names information—makes nominally typed most conservative measures, these languages are ex- OO languages closer to being semantically typed lan- pected to remain among the top most-used OO pro- guages than structurally typed OO languages are. gramming languages in the near future, if not the far The first mathematical models of OOP to gain one, too. widespread recognition among programming lan- In spite of this, the value of nominal typing and guages (PL) researchers were developed while OOP nominal subtyping to mainstream OO developers, as was making its first steps into mainstream computer a means for designing robust OO software that can programming. (See Section 2.) These early models be readily understood and maintained, as well as the were structural models of OOP. As the developers value of properties of OO type systems that depend of these models themselves (e.g., Cardelli) explained, on nominality to them (such as the identification of this was due to influence from functional program- type inheritance with subtyping), seem to be not yet ming research extant at that time. These models of fully appreciated among OO PL researchers. This OOP, thus, reflected a view of OOP that does not has led to a continuing tension and schism between include class names information. two large and significant communities: many main- Being structural, objects were viewed in these mod- stream OO developers and OO language designers, on els simply as being records (of functions). Object one side, and many OO PL researchers, on the other types, in accordance, were viewed as record types, side, with each of both sides discounting, and even where the type of an object only specifies the struc- disregarding, the views and opinions of the other. ture of the object, meaning that object types carry In nominally-typed (a.k.a., nominatively-typed) information only on the names of the members of ob- OO languages, objects and their types are nomi- jects (i.e., fields and methods) and, inductively, on nal, meaning that objects and their types carry class the (structural) types of those members. Examples names information as part of the meaning of objects of structurally-typed OO languages include lesser- and of the meaning of their types. Class names— known languages such as O’Caml [48], Modula-3 [27], 2 Moby [39], PolyTOIL [21], and Strongtalk [19].1 In Given that structural typing, more or less, is under- pure structurally-typed OO languages, class names stood well among PL researchers, in Section 3 we di- information (also called nominal information) is not rectly demonstrate the value of behavioral contracts used as part of the identity of objects and their types, and nominal typing in mainstream nominally-typed neither during static type checking nor at runtime. OO languages using a comparison, followed by a dis- Accordingly, nominal information is missing in struc- cussion of the comparison. In Section 3.1 we first tural mathematical models of OOP. discuss, in some detail, the value of contracts and The main practical advantage of structural typing the value of identifying inheritance with subtyping in over nominal typing in OO languages seems to be mainstream OO software design. Then, using code their “flexibility,” i.e., the ability in a structurally- examples, in Section 3.2 and Section 3.3 we compare typed OO language to have supertypes get defined nominally-typed OO type systems and structurally- “after the fact” (i.e., after their subtypes are already typed ones to more vividly illustrate the main tech- defined). In light of mainstream OO developers of nical differences between them. We then conclude in statically-typed OO languages not adopting struc- Section 3.4 by discussing the nominal and structural tural typing, the “inflexibility” of nominally-typed views of type names and of recursive-types, and the OO languages seems not to be enough justification for importance of recursive types in mainstream OOP. wider use of structural typing, particularly in light of We conclude the essay by summarizing our find- the advantages of nominal typing we discuss in this ings, and making some final remarks, in Section 4. essay. We attempt thus in this essay to further close the gap that exists between programming language 2 Related Work researchers who maintain a structurally-typed view of OOP (and who believe in conclusions based on Even though object-oriented programming emerged this view, such as inheritance and subtyping not be- in the 1960s, and got mature and well-established ing in one-to-one correspondence) and mainstream in mainstream software development in the 1980s, OO software developers and OO language design- the differences between nominally-typed and ers who maintain a nominally-typed view of OO structurally-typed OO programming languages software (and who, accordingly, reject conclusions started getting discussed by PL researchers only based on the structural view) by giving a precise in the 1990s [53, 65, 68]. In spite of an early hint technical account of the relation between nominal by Cardelli (see below), the value of investigating and structural OO type systems.
Recommended publications
  • Lackwit: a Program Understanding Tool Based on Type Inference
    Lackwit: A Program Understanding Tool Based on Type Inference Robert O’Callahan Daniel Jackson School of Computer Science School of Computer Science Carnegie Mellon University Carnegie Mellon University 5000 Forbes Avenue 5000 Forbes Avenue Pittsburgh, PA 15213 USA Pittsburgh, PA 15213 USA +1 412 268 5728 +1 412 268 5143 [email protected] [email protected] same, there is an abstraction violation. Less obviously, the ABSTRACT value of a variable is never used if the program places no By determining, statically, where the structure of a constraints on its representation. Furthermore, program requires sets of variables to share a common communication induces representation constraints: a representation, we can identify abstract data types, detect necessary condition for a value defined at one site to be abstraction violations, find unused variables, functions, used at another is that the two values must have the same and fields of data structures, detect simple errors in representation1. operations on abstract datatypes, and locate sites of possible references to a value. We compute representation By extending the notion of representation we can encode sharing with type inference, using types to encode other kinds of useful information. We shall see, for representations. The method is efficient, fully automatic, example, how a refinement of the treatment of pointers and smoothly integrates pointer aliasing and higher-order allows reads and writes to be distinguished, and storage functions. We show how we used a prototype tool to leaks to be exposed. answer a user’s questions about a 17,000 line program We show how to generate and solve representation written in C.
    [Show full text]
  • Scala−−, a Type Inferred Language Project Report
    Scala−−, a type inferred language Project Report Da Liu [email protected] Contents 1 Background 2 2 Introduction 2 3 Type Inference 2 4 Language Prototype Features 3 5 Project Design 4 6 Implementation 4 6.1 Benchmarkingresults . 4 7 Discussion 9 7.1 About scalac ....................... 9 8 Lessons learned 10 9 Language Specifications 10 9.1 Introdution ......................... 10 9.2 Lexicalsyntax........................ 10 9.2.1 Identifiers ...................... 10 9.2.2 Keywords ...................... 10 9.2.3 Literals ....................... 11 9.2.4 Punctions ...................... 12 9.2.5 Commentsandwhitespace. 12 9.2.6 Operations ..................... 12 9.3 Syntax............................ 12 9.3.1 Programstructure . 12 9.3.2 Expressions ..................... 14 9.3.3 Statements ..................... 14 9.3.4 Blocksandcontrolflow . 14 9.4 Scopingrules ........................ 16 9.5 Standardlibraryandcollections. 16 9.5.1 println,mapandfilter . 16 9.5.2 Array ........................ 16 9.5.3 List ......................... 17 9.6 Codeexample........................ 17 9.6.1 HelloWorld..................... 17 9.6.2 QuickSort...................... 17 1 of 34 10 Reference 18 10.1Typeinference ....................... 18 10.2 Scalaprogramminglanguage . 18 10.3 Scala programming language development . 18 10.4 CompileScalatoLLVM . 18 10.5Benchmarking. .. .. .. .. .. .. .. .. .. .. 18 11 Source code listing 19 1 Background Scala is becoming drawing attentions in daily production among var- ious industries. Being as a general purpose programming language, it is influenced by many ancestors including, Erlang, Haskell, Java, Lisp, OCaml, Scheme, and Smalltalk. Scala has many attractive features, such as cross-platform taking advantage of JVM; as well as with higher level abstraction agnostic to the developer providing immutability with persistent data structures, pattern matching, type inference, higher or- der functions, lazy evaluation and many other functional programming features.
    [Show full text]
  • First Steps in Scala Typing Static Typing Dynamic and Static Typing
    CS206 First steps in Scala CS206 Typing Like Python, Scala has an interactive mode, where you can try What is the biggest difference between Python and Scala? out things or just compute something interactively. Python is dynamically typed, Scala is statically typed. Welcome to Scala version 2.8.1.final. In Python and in Scala, every piece of data is an object. Every scala> println("Hello World") object has a type. The type of an object determines what you Hello World can do with the object. Dynamic typing means that a variable can contain objects of scala> println("This is fun") different types: This is fun # This is Python The + means different things. To write a Scala script, create a file with name, say, test.scala, def test(a, b): and run it by saying scala test.scala. print a + b In the first homework you will see how to compile large test(3, 15) programs (so that they start faster). test("Hello", "World") CS206 Static typing CS206 Dynamic and static typing Static typing means that every variable has a known type. Dynamic typing: Flexible, concise (no need to write down types all the time), useful for quickly writing short programs. If you use the wrong type of object in an expression, the compiler will immediately tell you (so you get a compilation Static typing: Type errors found during compilation. More error instead of a runtime error). robust and trustworthy code. Compiler can generate more efficient code since the actual operation is known during scala> varm : Int = 17 compilation. m: Int = 17 Java, C, C++, and Scala are all statically typed languages.
    [Show full text]
  • Typescript-Handbook.Pdf
    This copy of the TypeScript handbook was created on Monday, September 27, 2021 against commit 519269 with TypeScript 4.4. Table of Contents The TypeScript Handbook Your first step to learn TypeScript The Basics Step one in learning TypeScript: The basic types. Everyday Types The language primitives. Understand how TypeScript uses JavaScript knowledge Narrowing to reduce the amount of type syntax in your projects. More on Functions Learn about how Functions work in TypeScript. How TypeScript describes the shapes of JavaScript Object Types objects. An overview of the ways in which you can create more Creating Types from Types types from existing types. Generics Types which take parameters Keyof Type Operator Using the keyof operator in type contexts. Typeof Type Operator Using the typeof operator in type contexts. Indexed Access Types Using Type['a'] syntax to access a subset of a type. Create types which act like if statements in the type Conditional Types system. Mapped Types Generating types by re-using an existing type. Generating mapping types which change properties via Template Literal Types template literal strings. Classes How classes work in TypeScript How JavaScript handles communicating across file Modules boundaries. The TypeScript Handbook About this Handbook Over 20 years after its introduction to the programming community, JavaScript is now one of the most widespread cross-platform languages ever created. Starting as a small scripting language for adding trivial interactivity to webpages, JavaScript has grown to be a language of choice for both frontend and backend applications of every size. While the size, scope, and complexity of programs written in JavaScript has grown exponentially, the ability of the JavaScript language to express the relationships between different units of code has not.
    [Show full text]
  • Certifying Ocaml Type Inference (And Other Type Systems)
    Certifying OCaml type inference (and other type systems) Jacques Garrigue Nagoya University http://www.math.nagoya-u.ac.jp/~garrigue/papers/ Jacques Garrigue | Certifying OCaml type inference 1 What's in OCaml's type system { Core ML with relaxed value restriction { Recursive types { Polymorphic objects and variants { Structural subtyping (with variance annotations) { Modules and applicative functors { Private types: private datatypes, rows and abbreviations { Recursive modules . Jacques Garrigue | Certifying OCaml type inference 2 The trouble and the solution(?) { While most features were proved on paper, there is no overall specification for the whole type system { For efficiency reasons the implementation is far from the the theory, making proving it very hard { Actually, until 2008 there were many bug reports A radical solution: a certified reference implementation { The current implementation is not a good basis for certification { One can check the expected behaviour with a (partial) reference implementation { Relate explicitly the implementation and the theory, by developing it in Coq Jacques Garrigue | Certifying OCaml type inference 3 What I have be proving in Coq 1 Over the last 2 =2 years (on and off) { Built a certified ML interpreter including structural polymorphism { Proved type soundness and adequacy of evaluation { Proved soundness and completeness (principality) of type inference { Can handle recursive polymorphic object and variant types { Both the type checker and interpreter can be extracted to OCaml and run { Type soundness was based on \Engineering formal metatheory" Jacques Garrigue | Certifying OCaml type inference 4 Related works About core ML, there are already several proofs { Type soundness was proved many times, and is included in "Engineering formal metatheory" [2008] { For type inference, both Dubois et al.
    [Show full text]
  • Bidirectional Typing
    Bidirectional Typing JANA DUNFIELD, Queen’s University, Canada NEEL KRISHNASWAMI, University of Cambridge, United Kingdom Bidirectional typing combines two modes of typing: type checking, which checks that a program satisfies a known type, and type synthesis, which determines a type from the program. Using checking enables bidirectional typing to support features for which inference is undecidable; using synthesis enables bidirectional typing to avoid the large annotation burden of explicitly typed languages. In addition, bidirectional typing improves error locality. We highlight the design principles that underlie bidirectional type systems, survey the development of bidirectional typing from the prehistoric period before Pierce and Turner’s local type inference to the present day, and provide guidance for future investigations. ACM Reference Format: Jana Dunfield and Neel Krishnaswami. 2020. Bidirectional Typing. 1, 1 (November 2020), 37 pages. https: //doi.org/10.1145/nnnnnnn.nnnnnnn 1 INTRODUCTION Type systems serve many purposes. They allow programming languages to reject nonsensical programs. They allow programmers to express their intent, and to use a type checker to verify that their programs are consistent with that intent. Type systems can also be used to automatically insert implicit operations, and even to guide program synthesis. Automated deduction and logic programming give us a useful lens through which to view type systems: modes [Warren 1977]. When we implement a typing judgment, say Γ ` 4 : 퐴, is each of the meta-variables (Γ, 4, 퐴) an input, or an output? If the typing context Γ, the term 4 and the type 퐴 are inputs, we are implementing type checking. If the type 퐴 is an output, we are implementing type inference.
    [Show full text]
  • 1 Polymorphism in Ocaml 2 Type Inference
    CS 4110 – Programming Languages and Logics Lecture #23: Type Inference 1 Polymorphism in OCaml In languages like OCaml, programmers don’t have to annotate their programs with 8X: τ or e »τ¼. Both are automatically inferred by the compiler, although the programmer can specify types explicitly if desired. For example, we can write let double f x = f (f x) and OCaml will figure out that the type is ('a ! 'a) ! 'a ! 'a which is roughly equivalent to the System F type 8A: ¹A ! Aº ! A ! A We can also write double (fun x ! x+1) 7 and OCaml will infer that the polymorphic function double is instantiated at the type int. The polymorphism in ML is not, however, exactly like the polymorphism in System F. ML restricts what types a type variable may be instantiated with. Specifically, type variables can not be instantiated with polymorphic types. Also, polymorphic types are not allowed to appear on the left-hand side of arrows—i.e., a polymorphic type cannot be the type of a function argument. This form of polymorphism is known as let-polymorphism (due to the special role played by let in ML), or prenex polymorphism. These restrictions ensure that type inference is decidable. An example of a term that is typable in System F but not typable in ML is the self-application expression λx: x x. Try typing fun x ! x x in the top-level loop of OCaml, and see what happens... 2 Type Inference In the simply-typed lambda calculus, we explicitly annotate the type of function arguments: λx : τ: e.
    [Show full text]
  • An Overview of the Scala Programming Language
    An Overview of the Scala Programming Language Second Edition Martin Odersky, Philippe Altherr, Vincent Cremet, Iulian Dragos Gilles Dubochet, Burak Emir, Sean McDirmid, Stéphane Micheloud, Nikolay Mihaylov, Michel Schinz, Erik Stenman, Lex Spoon, Matthias Zenger École Polytechnique Fédérale de Lausanne (EPFL) 1015 Lausanne, Switzerland Technical Report LAMP-REPORT-2006-001 Abstract guage for component software needs to be scalable in the sense that the same concepts can describe small as well as Scala fuses object-oriented and functional programming in large parts. Therefore, we concentrate on mechanisms for a statically typed programming language. It is aimed at the abstraction, composition, and decomposition rather than construction of components and component systems. This adding a large set of primitives which might be useful for paper gives an overview of the Scala language for readers components at some level of scale, but not at other lev- who are familar with programming methods and program- els. Second, we postulate that scalable support for compo- ming language design. nents can be provided by a programming language which unies and generalizes object-oriented and functional pro- gramming. For statically typed languages, of which Scala 1 Introduction is an instance, these two paradigms were up to now largely separate. True component systems have been an elusive goal of the To validate our hypotheses, Scala needs to be applied software industry. Ideally, software should be assembled in the design of components and component systems. Only from libraries of pre-written components, just as hardware is serious application by a user community can tell whether the assembled from pre-fabricated chips.
    [Show full text]
  • Class Notes on Type Inference 2018 Edition Chuck Liang Hofstra University Computer Science
    Class Notes on Type Inference 2018 edition Chuck Liang Hofstra University Computer Science Background and Introduction Many modern programming languages that are designed for applications programming im- pose typing disciplines on the construction of programs. In constrast to untyped languages such as Scheme/Perl/Python/JS, etc, and weakly typed languages such as C, a strongly typed language (C#/Java, Ada, F#, etc ...) place constraints on how programs can be written. A type system ensures that programs observe logical structure. The origins of type theory stretches back to the early twentieth century in the work of Bertrand Russell and Alfred N. Whitehead and their \Principia Mathematica." They observed that our language, if not restrained, can lead to unsolvable paradoxes. Specifically, let's say a mathematician defined S to be the set of all sets that do not contain themselves. That is: S = fall A : A 62 Ag Then it is valid to ask the question does S contain itself (S 2 S?). If the answer is yes, then by definition of S, S is one of the 'A's, and thus S 62 S. But if S 62 S, then S is one of those sets that do not contain themselves, and so it must be that S 2 S! This observation is known as Russell's Paradox. In order to avoid this paradox, the language of mathematics (or any language for that matter) must be constrained so that the set S cannot be defined. This is one of many discoveries that resulted from the careful study of language, logic and meaning that formed the foundation of twentieth century analytical philosophy and abstract mathematics, and also that of computer science.
    [Show full text]
  • Local Type Inference
    Local Type Inference BENJAMIN C. PIERCE University of Pennsylvania and DAVID N. TURNER An Teallach, Ltd. We study two partial type inference methods for a language combining subtyping and impredica- tive polymorphism. Both methods are local in the sense that missing annotations are recovered using only information from adjacent nodes in the syntax tree, without long-distance constraints such as unification variables. One method infers type arguments in polymorphic applications using a local constraint solver. The other infers annotations on bound variables in function abstractions by propagating type constraints downward from enclosing application nodes. We motivate our design choices by a statistical analysis of the uses of type inference in a sizable body of existing ML code. Categories and Subject Descriptors: D.3.1 [Programming Languages]: Formal Definitions and Theory General Terms: Languages, Theory Additional Key Words and Phrases: Polymorphism, subtyping, type inference 1. INTRODUCTION Most statically typed programming languages offer some form of type inference, allowing programmers to omit type annotations that can be recovered from context. Such a facility can eliminate a great deal of needless verbosity, making programs easier both to read and to write. Unfortunately, type inference technology has not kept pace with developments in type systems. In particular, the combination of subtyping and parametric polymorphism has been intensively studied for more than a decade in calculi such as System F≤ [Cardelli and Wegner 1985; Curien and Ghelli 1992; Cardelli et al. 1994], but these features have not yet been satisfactorily This is a revised and extended version of a paper presented at the 25th ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages (POPL), 1998.
    [Show full text]
  • The Early History of F# (HOPL IV – Second Submitted Draft)
    The Early History of F# (HOPL IV – second submitted draft) DON SYME, Principal Researcher, Microsoft; F# Language Designer; F# Community Contributor This paper describes the genesis and early history of the F# programming language. I start with the origins of strongly-typed functional programming (FP) in the 1970s, 80s and 90s. During the same period, Microsoft was founded and grew to dominate the software industry. In 1997, as a response to Java, Microsoft initiated internal projects which eventually became the .NET programming framework and the C# language. From 1997 the worlds of academic functional programming and industry combined at Microsoft Research, Cambridge. The researchers engaged with the company through Project 7, the initial effort to bring multiple languages to .NET, leading to the initiation of .NET Generics in 1998 and F# in 2002. F# was one of several responses by advocates of strongly-typed functional programming to the “object-oriented tidal wave” of the mid-1990s. The development of the core features of F# happened from 2004-2007, and I describe the decision-making process that led to the “productization” of F# by Microsoft in 2007-10 and the release of F# 2.0. The origins of F#’s characteristic features are covered: object programming, quotations, statically resolved type parameters, active patterns, computation expressions, async, units-of-measure and type providers. I describe key developments in F# since 2010, including F# 3.0-4.5, and its evolution as an open source, cross-platform language with multiple delivery channels. I conclude by examining some uses of F# and the influence F# has had on other languages so far.
    [Show full text]
  • Haskell-Like S-Expression-Based Language Designed for an IDE
    Department of Computing Imperial College London MEng Individual Project Haskell-Like S-Expression-Based Language Designed for an IDE Author: Supervisor: Michal Srb Prof. Susan Eisenbach June 2015 Abstract The state of the programmers’ toolbox is abysmal. Although substantial effort is put into the development of powerful integrated development environments (IDEs), their features often lack capabilities desired by programmers and target primarily classical object oriented languages. This report documents the results of designing a modern programming language with its IDE in mind. We introduce a new statically typed functional language with strong metaprogramming capabilities, targeting JavaScript, the most popular runtime of today; and its accompanying browser-based IDE. We demonstrate the advantages resulting from designing both the language and its IDE at the same time and evaluate the resulting environment by employing it to solve a variety of nontrivial programming tasks. Our results demonstrate that programmers can greatly benefit from the combined application of modern approaches to programming tools. I would like to express my sincere gratitude to Susan, Sophia and Tristan for their invaluable feedback on this project, my family, my parents Michal and Jana and my grandmothers Hana and Jaroslava for supporting me throughout my studies, and to all my friends, especially to Harry whom I met at the interview day and seem to not be able to get rid of ever since. ii Contents Abstract i Contents iii 1 Introduction 1 1.1 Objectives ........................................ 2 1.2 Challenges ........................................ 3 1.3 Contributions ...................................... 4 2 State of the Art 6 2.1 Languages ........................................ 6 2.1.1 Haskell ....................................
    [Show full text]