The Quest for Programming Nirvana: on Programming Game Systems in Haskell
Total Page:16
File Type:pdf, Size:1020Kb
The Quest for Programming Nirvana: On Programming Game Systems in Haskell Alexander Berntsen Master’s Thesis Master of Science in Applied Computer Science 30 ECTS Department of Computer Science and Media Technology Gjøvik University College, 2014 Avdeling for informatikk og medieteknikk Høgskolen i Gjøvik Postboks 191 2802 Gjøvik Department of Computer Science and Media Technology Gjøvik University College Box 191 N-2802 Gjøvik Norway The Quest for Programming Nirvana: On Programming Game Systems in Haskell Alexander Berntsen 2014/06/01 The Quest for Programming Nirvana: On Programming Game Systems in Haskell Abstract This thesis identifies and substantiates the observation that purely functional programming (PFP) of game systems has reached a level of maturity that makes it a desirable alternative to the imperative object-oriented paradigm (OOP), which games are usually programmed in. Several papers suggest that PFP leads to source code which is easier to reason with than imperative code with side-effects. These papers do not consider problems specific to game programming, and do not have quantitative data to back up their conjectures. This thesis implements a game system in C++ and Haskell, and directly compares them, thereby motivating a discussion of PFP of game systems. The data suggests that PFP with Haskell is more suitable for game systems than C++ with the imperative OOP paradigm. The discussion identifies the substitution of equals for equals afforded by strongly and statically typed PFP am being the main reason for this, and highlights other advantages of PFP. Real world challenges of the Haskell ecosystem are analysed, and suggestions for improvement are offered. Further research on the use of PFP for game systems is suggested. iii The Quest for Programming Nirvana: On Programming Game Systems in Haskell Preface Thanks to my supervisor Mariusz Nowostawski for his guidance and help with the thesis, but above all for our discussions. Thanks to the following for helping improve and assure the quality of my thesis in various ways: Evan Czaplicki, Stian Ellingsen, Conal Elliott, Edward Kmett, Mette Pernille Hellesvik, Simon McCallum, Erik Moen, & Nuno J. Silva. Thanks to Niklas Haas for being a huge geek and getting me to finally sit down and learn Haskell. This thesis is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. (Included in Appendix H.) Alexander Berntsen, 2014/06/01 v The Quest for Programming Nirvana: On Programming Game Systems in Haskell Contents Abstract .............................................. iii Preface .............................................. v Contents ............................................. vii List of Figures .......................................... ix List of Tables ........................................... xi 1 Introduction ......................................... 1 1.1 Contributions . .2 2 Background ......................................... 3 2.1 Imperative Programming vs. Declarative programming . .3 2.2 Object-Oriented Programming vs. Purely Functional Programming . .3 2.3 Types and Kinds . .8 2.4 Polymorphism . 11 2.5 Turing completeness . 13 3 The Problem ......................................... 15 3.1 The Scope of the Thesis . 15 3.2 Motivation for the Thesis . 15 4 Related Work ......................................... 17 5 Methodology ......................................... 19 6 The Quest for Data ..................................... 23 6.1 Definitions . 23 6.2 Initial Implementation . 24 6.2.1 SLOC on program-level . 25 6.2.2 SLOC on Function Level . 26 6.3 Third-party projects . 28 6.4 Modifications . 34 6.4.1 First modification . 34 6.4.2 Second modification . 36 7 Discussion .......................................... 41 7.1 The Advantages of Declarative Programming . 41 7.2 The Advantages of Purely Functional Programming . 42 7.3 The Disadvantages of Subtype Polymorphism . 45 7.4 Typing . 46 7.5 Modules . 46 7.6 Optimisation . 46 7.7 Parallelism . 47 7.8 Using Haskell to do some of the job . 48 vii The Quest for Programming Nirvana: On Programming Game Systems in Haskell 7.9 What If You Really Need A Side-Effect? . 49 7.10 Space Leaks . 49 7.11 Anecdotal Remarks . 49 8 Other Considerations for Haskell Game Systems Programming ........... 51 8.1 The Haskell ecosystem . 51 8.1.1 The distributed runtime . 51 8.1.2 Portability . 51 8.1.3 Libraries . 51 8.1.4 Build tools . 52 8.1.5 Debugging and Profiling Tools . 52 8.1.6 Tests . 52 8.1.7 Integrated Development Environments . 52 8.2 Paradigms and Techniques Beyond Purely Functional Programming in Haskell . 53 8.2.1 Functional Reactive Programming . 53 8.2.2 Lenses . 54 9 Conclusions ......................................... 57 9.1 Is PFP “Better” Than Imperative OOP? . 57 9.2 Overcoming the Real World Problems . 58 9.3 Strong Static Typing . 59 10 Further Work ......................................... 61 10.1 Dependent Types . 61 10.2 Denotative and Imperative Programming . 61 10.3 Declaration and Expression Style . 62 10.4 Complexity . 63 10.5 The Human Factor . 63 10.6 Other Languages . 63 10.7 Reproducing and Augmenting the Data . 64 Bibliography ........................................... 67 A Notation ........................................... 73 A.1 λ-calculus . 73 A.2 Backus-Naur Form . 73 B Design document ...................................... 75 C C++ implementation .................................... 79 D Haskell implementation .................................. 159 E C++ commit log ....................................... 203 F Haskell commit log ..................................... 205 G Third-Party Functions .................................... 207 H CC-BY-SA Licence text .................................... 213 viii The Quest for Programming Nirvana: On Programming Game Systems in Haskell List of Figures 1 Three ways to add two numbers in C++ . .4 2 Making a new character based on the old character . .6 3 The monad laws . .6 4 The monads laws in Haskell . .7 5 A simple “guess-the-number” game in Haskell . .8 6 List as an example of a functor, applicative, and monad . .9 7 Examples of programming languages and their typing rules . 10 8 Expression type signature in Haskell . 10 9 Simple object-inheritance . 11 10 Addition acting differently on different types . 12 11 Length acting the same on different types . 12 12 A function for adding two numbers . 12 13 A System type class for handling events, which Foo and Bar are instances of . 13 14 Higher-kinded polymorphism with type classes . 14 15 Method overloading in C++ . 14 16 SLOC distribution per implementation . 25 17 SLOC distribution per implementation, disregarding comments and emptylines . 25 18 SLOC distribution for AutoTools and Cabal . 26 19 Estimated months of effort per implementation . 26 20 Lines of function code per implementation . 27 21 Lines of function code per implementation without context . 27 22 Median SLOC per function per implementation . 28 23 Median SLOC per function per implementation without context . 28 24 Mean SLOC per function per implementation . 29 25 Mean SLOC per function per implementation without context . 29 26 Median SLOC per function for third-party projects . 30 27 Median SLOC per function for third-party projects without context . 30 28 Mean SLOC per function for third-party Haskell projects . 31 29 Mean SLOC per function for third-party projects without context . 31 30 Amount of functions per SLOC count for third-party C++ projects . 32 31 Amount of functions per SLOC count for third-party C++ projects without context 32 32 Amount of functions per SLOC count for third-party Haskell projects . 33 33 Amount of functions per SLOC count for third-party Haskell projects without context 33 34 Histogram of amount of functions by SLOC count . 34 35 Histogram of amount of functions without context by SLOC count . 34 36 Added and removed lines for the first modification in C++ . 35 ix The Quest for Programming Nirvana: On Programming Game Systems in Haskell 37 Added and removed lines for the first modification in Haskell . 35 38 Changed files for the first modification . 36 39 Changed lines for the first modification . 36 40 Added and removed lines for the second modification in C++ . 37 41 Added and removed lines for the second modification in Haskell . 37 42 Changed files for the second modification . 38 43 Changed lines for the second modification . 38 44 Changed lines for both modifications . 39 45 Button drawing in C++ . 41 46 Button drawing in Haskell . 41 47 Laziness in action in the interactive Glasgow Haskell Compiler . 44 48 Allocating and freeing the memory for buttons in C++ . ..