It just works(™)!

I was recently a guest on the .NET Rocks podcast and one of the things that came up was this notion in F# of “if it compiles – it works”. Given the constraints of time on the show (and technical difficulties with sound on my end) I wanted to give a fuller take on why I think this is so, as I can imagine to people not used to F# (or Functional Programming) it may sound like Snake Oil.

No Nulls

Tony Hoare has referred to NULL as his billion dollar mistake. If you’ve written C#, C, C++, Java, et al, just stop and think about how many times you’ve hit unexpected Null Reference Exceptions (hell, the designers of Javascript thought it such a good idea they added “undefined” too!). These are usually trivial to fix – if you own the code. If the exception is in a framework then you might end up having to catch Null Reference Exceptions all over your code and deal with the uncertainty of the state that the unhanded exception has left you in.

In F# classes (and records) are non-nullable by default. This means that if you stick with the happy path you cannot get a null reference exception (in your own code). If you really need to represent a state of Something or Nothing then the Option type is a built in type that allows you to access the values safely via pattern matching or the Option module. Don Syme posted a very entertaining post about this close to a year ago (I wonder if Don should call it his billion dollar saving?).

Of course you can still have nullable classes in F#- but you have to explicitly state this with the AllowNullLiteral attribute – a clear indication that something may go wrong later.

But even Bret “The Hitman” Hart knows this is silly!!

And for the record – “?.” in C# 6 is a lame attempt to solve null in C#.

Immutability

In F# values are immutable by default. This means that state is consistent throughout the application. Imagine passing a list into a void method which add a value to the end. In F# (using the build in List type – which is of course immutable) the append would only affect the local copy of the list in the method – it would have no effect. To capture the change in F# you would have to change the void method (or unit in F#) to return the new list.

Immutability is often discussed as a great way to avoid data races in multithreaded code, but even in more trivial cases it is incredibly useful to know that the state of an object cannot change midway through a method. In C# you may not think twice about a series of void return methods which mutate properties/fields of a class, but this means the state of a class is constantly in flux which may make it hard to reason about it’s state at any given time. This often leads to bugs (especially if you can set references to NULL!).

F# is not a “pure” functional language – hence mutation is allowed, but only if you specify it. This means that by looking through your code for the mutable keyword or the <- operator you can identify potentially problematic areas of your code without even running it.

Return values must be explicitly ignored

Because by default a function has no side-effect, to ignore its result would have been effectively a no-op. The complier therefore forces you to explicitly ignore the return value and this removes an entire class of errors. If you are ignoring lots of results, it’s probably a code smell that you are mutating state in functions – the clue that you are doing something fishy is explicit in the code.

Functional SOLID

One of the things I talked about on the show was Functional SOLID. SOLID is a system which “intend(s) to make it more likely that a programmer will create a system that is easy to maintain and extend over time” (Wikipedia). For an OO programmer it is important to have rules about what to do to create clean extensible software because the defaults lead you to the opposite.

Breaking down how SOLID might apply to a functional language:

Single Responsibility – a function (by default) has no side-effect. Therefore values in => value out. A function therefore by default can only have a single responsibility.

Open-Close – a function can be extended (but not modified) by using higher order functions.

Liskov Substitution (design by contract) - a function signature could be said to be a  stable contract and using the default single responsibility of a function, you are more likely (but not guaranteed) to get the same behaviour, provided the contract is clearly defined. Use higher order functions in place of classes/interfaces.

Interface Segregation – what could be a smaller interface than a function? Use higher order functions in place of interfaces.

Dependency Inversion – what easier way to invert a dependancy than higher order functions?

When you read the above list, it boils down to 2 things – use functions and higher order functions. These are the defaults of functional programming (as opposed to rules imposed by programmers), hence there is no need for SOLID for functional languages.

I made up the term “Functional SOLID” simply to delete it. Consider it my Randall Stevens.

Even More!!!!

Boolean traps exist in all kinds of code – a simple true/false which should be one of the simplest things to reason about but often isn’t.  But things can get even more complex with numbers – what if the int that your function takes is supposed to represent quantity of apples and not seconds since the epoch.

Units of measure help make sure your float of Kg doesn’t end up being used as a float of metres.

But taking things at a more basic level, F# doesn’t even allow implicit conversion between number types – a relatively experienced C# programmer may guess correctly what type x is – and the pitfalls of the automatic conversion:

var x = 1.3 * 2;

but the F# programmer has the compiler watch his/her back:

let x = 1.3 * 2;
error FS0001: The type 'int' does not match the type 'float'

This may seem like paranoia, but as there is no clear default, the compiler default is to make you choose. Which seems fair enough to me.

Conclusion

It’s easy to become institutionalised in a world of OO, where null is the norm,  mutation is everywhere, and large unwieldy classes reign supreme. It doesn’t have to be that way.

Hopefully I’ve helped illustrate some of the ways that F# (and other functional languages) can help reduce common errors in code. As you can see from every example, it’s the default behaviour that gets you to the happy place. You can deviate should you want/need to, but that’s an explicit choice to opt-out of safety, whereas the default for OO languages is to have no safety by default.

Posted in C#, F#, thought | 4 Comments

Book Review: F# for Quantitative Finance

I was recently given the opportunity to review the book F# for Quantitative Finance by Johan Astborg. 

Cover

Disclaimer:

I work in the finance industry, but I don’t do “Quant stuff” for a living. I’m not going to review the correctness of the book as I have to trust the author and the proof readers. 

Book structure

The book has 3 distinct sections – an Introduction to F#, required maths knowledge, and then application of the previous 2 in the context of Black-Scholes and Monte Carlo, following through into volatility, options and a full trading app.

It’s hard to fault the structure – if theres anything I’m not sure I agree with is the F# briefing – Quantitative finance doesn’t seem like a great “Hello World” app so I’d expect most readers to already be familiar with the language before starting this book. That being said, a target audience of people who already know the techniques described in this book may find it handy to have a short (it’s about 75 pages) run through of the language to help them get through the later chapters where they may be more familiar with the subject, but less so with F#.

The next sections go through some basic maths (Averages, Variance, Standard Deviations) in F# and then introduces Math.NET for some of the more complex maths. Personally I think this is a wise choice – Math.NET is incredibly powerful and integrates well with F# and allows the author to spend more time on (at this stage) explaining what the methods mean (and plotting them using FsChart). Once a brief detour of using charts to display data from Yahoo Finance is made (which really showcases the power of F#) its into the options pricing and Black-Scholes formula (by this point around the halfway mark in the book). 

At this point you are really going to want to read this near a PC (if you’ve not already). The algorithms are best understood by using a tactile approach in my opinion – in other words typing out the code and playing with it. It’s incredibly satisfying to see charts based of an algorithm you have just typed (but may barely understand at this point) and provides an excellent way to try to further understand. A description of Monte-Carlo method and the theory is over.

Next up is where it gets hairy. Exploring volatility is a really dense chapter and will probably require several re-reads to understand if you’re not already familiar with the subject. Luckily the author has a clear writing style – but the subject matter is just tricky to digest in 1 go. It doesn’t take long to move past and then we get back into more of F# strengths in domain modelling.

A nice detour into using QuickFIX/N for setting up a trading system (I’ve heard people moan about FIX, but certainly it doesn’t seem so scary with this library) and it’s back into trading options and strategies for trading options. This chapter is quite long and contains detailed explanations of some of the options strategies (such as long/short straddle and long/short butterfly) along with charts to show the payoff. It’s a code heavy chapter, and once again I’d recommend having Visual Studio handy to play with the code.

Finally a trading screen is built up using the information from the previous 6 chapters, which really helps solidify some of the concepts previously described. It’s worth spending some time to at least have a basic understanding of whats come before as this chapter does reference a lot of the previous techniques without heavily retreading it. The book is then finished off with an appendix.

Content

The F# code is neatly laid out and most samples weigh in at under 1 page. One thing I especially appreciate is type annotations in the book – without the benefit of intellisense this is a godsend for helping digest an already tricky topic. 

The samples make nice use of FSChart for visualisation, which helps keep the noise ratio down when charting, although a couple of samples do seem to go the extra mile to show how to do a full WinForms app in place of just FSChart – I’m not sure if there’s a reasoning behind this.

The writing style does vary a little – the more intense chapters are a little terser in terms of explanation, but the code is usually sufficient to provide a starting point for self-discovery. In the “lighter” chapters, the writer covers the topics swiftly, but with plenty of detail. 

The book weighs in at just under 300 pages, which means it’s not especially heavyweight, but it does cover a lot of ground. Personally, I’d ditch the F# tutorial at the beginning, but then I already know F#. 

Summary

F# for Quantitative Finance is a handy book to read if you’ve an interest in quantitative finance. It’s well written and utilises key strengths of F# to make the topic less scary (although by no means easy). I’m not hugely qualified to say how complete a book it is, but what it does cover is clearly written and understandable.

F# for Quantitative Finance is available here.

Posted in F#, Review | Tagged , | 1 Comment

Building a C# compiler in F#

A little over a year ago I wrote a post about Roslyn.

Recently (after seeing Mads Torgersen‘s excellent NDC-london talk) I was inspired to attempt to write my own mini-C# compiler to address some of the missing features in C#.

Mads Torgersen repeating what I said a year ago

Mads Torgersen repeating what I said a year ago

Roslyn

Roslyn is a Microsoft project to rewrite the VB and C# compilers in their respective languages. After Mads talk, and listening to the (proposed) new features for C# 6 I couldn’t help but feel a little underwhelmed with the direction of C#.

Mads’ justification seems reasonable on the face of it – C# 2, 3,4 & 5 have all had major new language additions (namely generics, linq, dynamic & async) and that C# 6 is more of a ‘tidy the pain points’ release. But I had a number of ideas for improvements, and unfortunately only two are in C#6 (primary constructor and read-only auto-properties).

To make matters worse, it is not one of the goals of Roslyn to allow language extensions – C# spec is still owned by the C# team, and Roslyn wont allow you to add your own syntax. I get this – it would be fairly terrible if every codebase was C# + custom changes. But I can understand the desire from users to at least open source Roslyn (especially as it doesn’t run on Mono according to Glenn Block of ScriptCS fame – although I haven’t verified this myself).

It was this desire to play with language features that MS are not going to implement that drew me to writing my own C# compiler.

Before we begin

Phil Trelford’s excellent series on writing a SmallBasic compiler has to be the the best intro to building a compiler in .NET today – it covers parsing and compiling actual code from SmallBasic. Interestingly we had the similar idea at the same time about writing a parser & compiler for C#.

Now, I didn’t do any compiler theory in uni, I’ve never written a compiler before and I’ve only ever looked at Reflection Emit in anger. But despite these limitations I have a fairly capable C# 0.5 compiler (in that it is a subset of the C# 1 compiler). Which means you can do it too – it took me less than a month.

The source code for the compiler is here. It currently supports compilation of

  1. Classes
    1. Methods
      1. Local Variables
      2. Return values
      3. for, while and do while loops
      4. Comparisons and arithmetic
      5. Method calls (static, instance and “this”, on built in and custom defined types)
      6. Constructor calls
    2. Fields (no initialization)
    3. Constructors
  2. Interfaces
    1. Methods
  3. Enums
    1. Custom values – always 0 based
  4. Empty Structs

Big things currently missing (most are trivial plumbing, but I’ve just not had time or inclination yet) -

  1. Foreach, lock, switch, if/else
  2. Full range of modifiers (ie static, virtual, sealed, etc)
  3. Properties
  4. Struct bodies
  5. Constructor Bodies
  6. Field initialization
  7. Inheritance
  8. Attributes

But even with those limitations it’s still possible to write some basic programs.

Given C# is a (fairly) rigid spec, and this is a small version I’ve allowed myself some liberties:

  • There is code that should compile that doesn’t (even with above limitations).
  • There is code that shouldn’t compile that does.
  • As this is my first attempt at a C# Abstract Syntax Tree (Abbr AST) there are bits that are (in retrospect) plainly wrong, but work OK for now. Phil’s C# AST is more robust and at some point I’ll switch to using his.
  • You can only compile 1 file at a time.
  • Performance is pretty weak (of the compiler). Given the above limitation it’s not a big deal, but you wouldn’t want to build entity framework with it (courtesy of F# for fun and profit).
  • There are entirely unimplemented features – some I will address, some I wont (switch for example is so weak in C# it doesn’t feel worth the effort).
  • Error messages are virtually non-existent – most compile errors are handled with a “failwith” which will simply throw an exception.
  • It can only compile DLLs currently.

I don’t want to go into too much detail about specifics of the code here – the full source is available if you want it, and you can ask me questions in the comments, should you feel the need. What I’d like to talk about is some of the conceptual issues from transforming a piece of text, into a loose structure, into a tighter structure, into IL.

Parsing C#

Phil’s blog post about parsing C# is an excellent start of turning C# code into F# Discriminated unions. I took a slightly different direction of using fslex and fsyacc to transform plain text into code, but the basic principle is the same – Discriminated Unions are great for describing Syntax Trees.

Both approaches to parsing have pros and cons. FParsec has some clear advantages of fslex/fsyacc – error messages are much better and you can easily use it from fsi while Fslex/fsyacc require a pre-compile step and are more verbose, but (to me) have an easier to learn syntax and a less steep learning curve. A more detailed comparison of fparsec vs parser-generator can be found here.

Transforming an AST into IL

Inception

Once we have a description of the code structure loaded into an AST  the fun begins. There are a number of problems solved by the C# compiler that are really convenient for the developer, but are tricky for the compiler writer.

  • No header files means that the compiler must decide the optimal path for generating types (unlike languages with header files where the public type definition must be predefined – by the programmer).
  • Mutually recursive types means that you cant simply compile in the order the code is presented.
  • Void as a type/not a type (Void exists in the system namespace, yet it doesn’t make sense as a type in any other place than a method declaration)
  • Null as a thing, but not really a thing.

You can think of the AST loaded from a text file as a loose representation of the code. You can write a completely valid AST that is utterly nonsensical from an execution point of view (for example calling non-existent methods, using undeclared values, type-mismatches, etc). One of the 1st tasks we need to do with this loose structure is to build it into a strongly typed and validatable AST. In the source I’ve simply gone from Expr to TExpr (where T stands for Typed).

To be able to build a typed representation we first need to stub out the type (class, interface or struct). This is because we may have a Method that returns an instance of a class defined later in the code. By “stubbing” the types we can stash them away to look up later.

Once we have stubbed the types, we need to do the same thing with the body of a type – a method may depend on a field, a property or another method, so we define the stub for methods ready to fill in later, but keep the method stub in a structure (in fact a tuple of method builder and a function to build it’s body) – think function prototypes in C. By the end of this stage we have a complete list of all user defined types, and members of those types, but importantly, there is no actual *code* emitted – purely code structure.

The “builder” function returned then converts the AST to a “Typed” AST, which is then validatable – I currently skip validation and skip to IL Generation. But it is now rich in metadata about the code – metadata which is used to convert the Typed AST into CIL.

Gotchas

The premise is actually deceptively simple – the devil is in the details.

  • The Reflection.Emit APIs do inheritance patently wrong – this cost me about 2 days of development time (although had I RTFM first I could have avoided this)
    • TypeBuilder derives from Type, so exposes Type’s methods, but they fall over at runtime unless you call CreateType first, which prevents further modification. The same problems apply to MethodBuilder (derives from MethodInfo), ConstructorBuilder (derives from ConstructorInfo), FieldBuilder (derives from FieldInfo) and PropertyBuilder (derives from PropertyInfo)
    • This means any userdefined types must be stored seperately from referenced assembly types for appropriate lookup on methods, fields, etc, rather than calling existing methods. F# really helps keep the ceremony down as you can partially apply functions pre-loaded with these definitions, rather than passing lots of data-structures around.
  • IL Generation is fairly finnicky – for example to call a method on a struct local variable you must load the struct using ldloca instead of the usual ldloc.
    • F# Pattern matching makes light work of handling these cases – once you know they exist.
    • The entire IL generator code which covers most use cases is ~150LOC. This is the most complex file in the project, but is hardly difficult.

Conclusion

People seem to be waiting for Roslyn to solve either meta-programming or scripting problems they either have now or think they’ll have in the future. The excellent .NET Rocks podcast has had a lot of people on recently to talk about what they’ve either done with Roslyn or plan to do, and it feels like a lot of it is entirely plausible without Roslyn.

The spirit of this post is to encourage you to not wait and to build it yourself. You probably don’t need the full C# 5 experience for a scripting language in your app. Rather than wait (Roslyn still has no official release date) I want to show you that it is not only possible, but entirely feasible to do this right now with a little thought as to what you are going to achieve – the provided source provided weighs in around only 800 lines of code so it’s not heavyweight by any stretch. The worst case scenario is that you rewrite your feature using Roslyn (once it is released)/Mono C# Compiler/CSharpCodeProvider, and you have some fun and learn something new in the meantime. Which doesn’t seem like such a bad case. Remember kids – this is the year of code - time to stop procrastinating and write something!

F# is a powerful choice for writing a compiler – Discriminated Union types, Record-Types, pattern-matching, immutable-by-default (the code provided is almost purely immutable – I cheated in 1 place, with a generic dictionary) and 1st class function and tuples makes light work of defining a syntax tree and transforming it into executable IL code. In fact I can’t begin to imagine how painful it would be to write a compiler without these features……

Code – https://github.com/neildanson/MicroCS

Posted in C#, Compiler, F# | 4 Comments

Building Mono on a Raspberry Pi (Hard Float)

The cool thing about the Raspberry Pi is that it is really really cheap and really really popular.

Until recently the worst thing about the Raspberry Pi has been the lack of hardfp version of Mono, leaving us .NET developers with 2 options:

  1. Learn something new (like Scala)
  2. Run the softfp Mono on the older Debian Squeezy Linux Distro

Now I know C# developers will be balking at the idea of #1, which only leaves #2.

Until now…….

Now Mono supports hardfp and a recent Mono (3.2.7), which is Good News(tm) as that means it supports the sgen GC as we’ll has the hardware floating point extensions on the ARM6 on the Pi.

Instructions are available here, but I hit a couple of small wrinkles on a fresh Raspbian install, so for my benefit and yours:

Step by Step

A couple of people have commented about how they needed to sudo some of these things (I didn’t need to – don’t know why), but remember, when in doubt sudo

  1. Ensure you have 2GB+ free on your SD card and a lot of time to spare
  2. Launch a terminal window/ssh into your Pi
  3. sudo apt-get update
  4. sudo apt-get install mono-complete
  5. sudo apt-get install automake
  6. sudo apt-get install libtool
  7. git clone git://github.com/mono/mono.git
  8. cd mono
  9. ./autogen.sh –prefix=/usr/local –enable-nls=no 
  10. Note the above step reads two dashes before prefix and enable-nls. Thanks crazy fonts (and eagle eyed readers)
  11. sudo make
  12. Wait a long time (6 hours +)
  13. Ignore the errors and hope they don’t mean anything
  14. sudo make install
  15. Wait some more
  16. Ignore the errors and hope they don’t mean anything
  17. PROFIT!

Now type mono –version and hopefully see this:

pi@raspberrypi ~/mono $ mono --version
Mono Runtime Engine version 3.2.7 (master/e94da6d Tue Dec 10 00:31:36 UTC 2013)
Copyright (C) 2002-2013 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
TLS:           __thread
SIGSEGV:       normal
Notifications: epoll
Architecture:  armel,vfp+hard
Disabled:      none
Misc:          softdebug 
LLVM:          supported, not enabled.
GC:            sgen

For directions on how to be able to build and run Winforms apps see this excellent post here

Posted in C#, Mono, Uncategorized | 28 Comments

Desktop class performance on a mobile phone?

I recently bought an iPhone 5S (this is partly why I’ve taken a short detour from the platform game – this will resume in my next post!). Once again Apple have managed to create hype around a new CPU which (according to Apple) is as powerful as a desktop PC. Now a desktop PC could range from a crappy little Atom to a new Mac Pro, so the term is perhaps a little vague.

I’m going to try to define it :)

So I go back to my Raytracer. Modified the code a tiny amount, so it runs on my Mac under Mono and iOS under Xamarin iOS. This seems pretty fair to me – Mono-a-Mono if you will. Then I moved it to Android and tested on Windows as well – because why not?

So how does a mobile ARM Dual Core CPU running (according to reports) somewhere around 1.3Ghz compare to an i7 Quad Core with hyper-threading @2.6Ghz? Or a Snapdragon quad-core on a different mobile OS?

All builds in release mode, tested outside the debugger (in no particular order):

Device Time OS Runtime CPU Spec
iPhone 5S 3.43 iOS 7 Xamarin iOS 7.03 (sgen/llvm) A7@1.3Ghz x2
Macbook Pro Retina (2012) (i7 3720QM) 1.04 MacOS Mavericks Mono 3.3 sgen i7 @2.6Ghz x4 (x2 HT)
Macbook Pro Retina (2012) 0.20 Windows 7 .NET 4.5 i7 @2.6Ghz x4 (x2 HT)
iPad 3 9.6 iOS 7 Xamarin iOS 7.03 (sgen/llvm) A5X @1Ghz x2
iPod Touch 4th Gen DNF iOS 6 Xamarin iOS 7.03 (sgen/llvm) A4 @ 800Mhz
Nexus 7 (2013) 2.5 Android Jelly Bean 4.3 Xamarin Android 4.10 Snapdragon S4 @ 1.4Ghz x4
Samsung S4 3.2 Android Jelly Bean 4.3 Xamarin Android 4.10 Snapdragon 600 @1.8Ghz x4
i7 W3520 0.68 Windows 7 .NET 4.5 i7 Xeon @2.67Ghz x4 (x2HT)
i5 E6410 0.44 Windows 7 .NET 4.5 i5 @2.67Ghz x2 (x2HT)
Intel Atom 5.32 Windows 8.1 .NET 4.5 N270 @ 1.6Ghz (x2HT)

Try the code on your own machine – source here (as I quickly and dirtily knocked this together you’ll see I don’t do any clever code sharing – maybe a second pass later!). I haven’t optimised this at all, but the core code is *exactly the same* so is as fair as I can make it – the only different is how the results are displayed.

What does this prove?

Nothing really. But I was bored and fancied seeing how fast my own code ran on my new toy. Is the A7 a desktop class processor? Well it’s somewhere between an Intel Atom and an Snapdragon S4/600, so you should make your own call there. It’s pretty fast, regardless of how it compares to a desktop CPU.

There are some unexpected results above – the i5 being faster than the i7 Xeon and the Nexus 7 being faster than the S4, but each test was run multiple times and the figures were the average of 3 runs with outliers excluded.

I guess if anything it proves that Microsoft/Xamarin have done an awesome job on giving me the tools to have an idea, code it in minutes and run it on 4 different platforms really easily. And that’s a good thing, right?

Posted in Android, benchmarking, F#, iOS, Mono, performance | Tagged , , , , , | 2 Comments

A Platform game in F# and SpriteKit – Part 7 – DSLs baby!

So far our (1) level is fairly painful code to look at – admittedly SpriteKit and F# take something that could have been horrific and simply make it tedious. Today we change that.

DSL

According to Wikipedia a DSL is

domain-specific language (DSL) is a computer language 
specialized to a particular application domain.

The domain in question for us is modelling a level.

F#’s light syntax mode means that it is ideal for building DSLs, along with record types, discriminated unions, and list comprehensions.

When building a DSL I tend to like to think about how I would like the “language” to look. Usually I want as little noise as possible, so that it almost looks like a plain text or simple markup/markdown file. Sometimes I want to include some F# code in the body but in a boiled down minimalist way.

When I think about the level I think of it as a couple of things -

  1. A bag of sprites I will interact with
  2. A music file I will play
  3. A non-interactive background I will draw but not interact with

You could expand this to include things like level rules (i.e. lower gravity for a level set in space), but the point of a DSL is to build it to suit your own domain – the above suits me for now. The great part about an internal DSL is that as it is real code, when “for now” changes, the compiler will tell me and don’t have to go into a bunch of (text? binary??!?) files and play with the content until I fix it up.

(Diversion) DSLs and Boolean Traps

A boolean trap is a term used for a part of the code where a boolean value is passed as a parameter and the intention is not clear or is counter intuitive to the expected behaviour. Languages like C# and Java allow you to define enums, which allow more expressive behaviour, but at the expense of added code (both the definition and the consumption of the enum).

F# allows for Discriminated unions, which allow you to define a new type and consume it with no ceremony.

Example (boolean trap version):

createPhysicsBody true

Obviously it’s pretty difficult to see what the true represents. C# can do it better by using enums, but the inclusion of the enum name every time is clumsy:

enum PhysicsBodyShape = { Circle, Rectangle }
createPhysicsBody(PhysicsBodyShape.Rectangle)

F# goes above and beyond with Discriminated Unions as the definition is lightweight and the consumption is trivial – F#’s type inference has your back:

type Shape = Rectangle | Circle
createPhysicsBody Rectangle

In F# it’s really easy to avoid these boolean traps, and there’s not really a good reason not to when designing an API/DSL.

Back to the language

Taking a look at the (1st pass) DSL for levels it’s really neat to see that it fits nicely on 1 page:

 [<AutoOpen>]
 module LevelDSL

 open MonoTouch
 open MonoTouch.CoreGraphics
 open MonoTouch.SpriteKit

 // Repeat action 1 time, n times or infinitely
 type RepeatAction = Once | Times of int | Forever
 type Seconds = float
 type TextureName = string

 type Path = 
 | Ellipse of int * int * int * int //Bounding rectangle
 // TODO Other path types

 // A thing can either be at a single point or follow a path over time (n times)
 type Location = 
 | Point of int * int
 | Path of Path * Seconds * RepeatAction 

 //The Shape used for Physics
 type Shape =
 | Rectangle 
 | Circle

 //Details about the Physics
 type Physics = 
 | NoPhysics
 | Static of Shape
 | Dynamic of Shape
 | DynamicNoGravity of Shape

 //Lightweight sprite definition
 type Sprite =
 | Sprite of TextureName * Location * Physics * Sprite list

 type Level = {
     Name : string
     Level : Sprite list
     Background : Sprite list }

Now with anything, there are parts I can see already that I think could be better, for example the background (parallax) layer is made up of “Sprite”s, which means you could inadvertantly enable physics for the background – this probably isn’t desirable! As with anything there’s a cost-benefit ratio and ultimately you need to decide how important some of these things are when building a DSL. In my case I am the sole consumer of this DSL so I’ll probably let it slide for now.

Also note that we use Type Abbreviations – this is yet another way we can avoid the boolean (or in this case float and string) trap in F#!

So let’s see how using our new shiny DSL looks when recreating level 1:

let level1 = {
     Name = "Level1"
     Level = [ for i in 0..100 -> Sprite("grass", Point(i * 70, 0), Static Rectangle, []) 
               for i in 104..200 -> Sprite("grass", Point(i * 70, 0), Static Rectangle, [])
               yield 
                 Sprite("stoneMid", 
                     Path(Ellipse(50,150,200,200), 3.0, Forever), 
                     Static(Rectangle),
                     [ Sprite("stoneLeft", Point(-70,0), Static Rectangle, [])
                       Sprite("stoneRight", Point(70,0), Static Rectangle, [])])
               ]

     Background = [ for i in 0..150 -> Sprite("hill_small", Point(i * 70, 50), NoPhysics, []) ]

Now this is all done inline in the level definition – as I’m storing the levels in modules I could even go a step further by adding another mini language on top of the DSL – so my level definition ends up something something like this:

Level = [ yield! platform 0
          yield! platform 104
          yield movingEllipsePlatform 50 150 ]

Ultimately it’s up to you to figure out what works best for you. Now, given we have spent so long defining a neat DSL, it would be a shame to not use it to spruce up the level with a new fixture – some steps:

let steps xpos = 
    [ for x in 1..3 do
        for y in 1..x do
            yield Sprite("grass", Point((x+xpos)*70, y*70), Static(Rectangle), []) ]

And consuming them to add more stuff to our level:

Level = [ yield! platform 0
          yield! platform 104
          yield! steps 20
          yield! steps 97
          yield! steps 110
          yield movingEllipsePlatform 50 150
          yield movingEllipsePlatform 1000 150
          yield movingEllipsePlatform 3000 150]

Finishing off

Today we’ve taken around 50 lines of code which was highly cohesive with SpriteKit and replaced it with a small DSL which allows us to break out the intent of those 50 lines into 3 lines, whilst also decoupling the API. Creating new levels is now much easier and any future changes to the level format will be caught by the F# compiler – an advantage that external DSLs cannot match.

Next time we’ll actually add a second level and a score which we can keep track of between levels until we either die or complete the game.

All the code for today is here

Posted in F#, iOS | Tagged , , , | 1 Comment

A Platform game in F# and SpriteKit – Part 6 – Death

If there’s one thing we can all be certain of in life, it’s death. And so the same rule must apply to our dude. It’s been good knowing you little guy.

F# shines again

The last few posts have been back on the “How SpriteKit works”, but this time I’m firmly back in “Why F# rocks” territory.

The shining example of F# goodness? First class events (again!) and discriminated unions.

Let’s start with the latter – if you haven’t come across discriminated unions before, then you can think of them as enums on steroids. Here’s our example today -

type LevelComplete = | Died | Continue

Now this is the most basic kind of discriminated union, which doesn’t give us anything more than an enum. But later I can embellish this to do something like:

type LevelComplete = | Died of int (*Final Score*) 
                     | Continue of int * int (*Score & Lives remaining*)

In short – it allows us to classify data under the LevelComplete type and pattern match to extract extra data. If you’re new to F# the concept may be new to you (buy this book NOW)- if you’re an old hand then you probably already know more than I do.

So we now have a type – but how do we use/consume this?

Well just like how we used the tap as an exit condition for the intro screen, or a timeout on the game over screen, we can set some rules in our update. For now the rules will be simple -

If the player falls off the bottom of the screen -> Died
If the player runs a certain distance -> Continue

Here’s the code:

let levelCompleteEvt = Event<_>()
use _ = scene.DidSimulatePhysicsEvent.Publish.Subscribe(fun _ -> 
    scrollNode.Position <- PointF(320.f - player.Position.X,0.0f)
    parallaxScrollNode.Position <- PointF(-player.Position.X / 2.f, 0.f)
    if player.Position.X > 10000.f then 
    levelCompleteEvt.Trigger Continue
    if player.Position.Y < -100.f then
    levelCompleteEvt.Trigger Died
)

As you can see we trigger an event to say what happened (new code highlighted in bold) (did I mention before first class events in F# are cool?). Then like the other async workflows we AwaitEvent on the new event (why oh why oh why was this omitted from C# async/await?).

let! levelComplete = Async.AwaitEvent levelCompleteEvt.Publish
return levelComplete

But then we return the result – this way we can control flow in that main game loop -

//Define the loop
let rec gameLoop() = async {
   do! startScreen()
   let! levelEnd = level1()
   match levelEnd with
   | Continue -> do! success()
   | Died -> do! gameOver()
   return! gameLoop()
}

Now you can see that we are able to reward the player for succeeding, and humiliate them for dying.

I’m not going to cover the awesome success() screen – you should run it an experience it’s awesomeness :). Hint: it uses SpriteKit particles, which Dave Thomas wrote about righthere.

More levels

Now I’m not going to go into too much here, other than lay some groundwork, but as a goal it would be nice to

  1. Support multiple levels
  2. If it was easy to write levels
  3. Be scalable

In my latest checkin I’ve added in some comments in the level() async workflow to highlight the level loading code (which should be changeable) and the player code (which should be the same for every level).

There are a couple of ways I can think of to handle multiple levels:

  • Have level take a higher order function and I could pass in functions to build levels (this doesn’t address #2 as every function is going to be bogged down in SpriteKit code)
  • Define an external file format (probably XML or JSON based) – this supports #1 and #2, but changes to the format are very brittle and not too scalable.
  • Define an internal DSL to define the data and a parser to turn the data into a level – I think this addresses #3 as breaking changes will force the project to not build – less chance of runtime errors or breaking changes. Once again, this plays right into F# strengths.

If anyone has a 4th suggestion, please feel free to post a comment!

So next time I’ll probably build a simple DSL to represent a level and then cover loading it in in a future post.

Code for today

All the code

Posted in F#, iOS | Tagged , , , | 1 Comment