Multiple items
module List
from Microsoft.FSharp.Collections
--------------------
type List<'T> =
| ( [] )
| ( :: ) of Head: 'T * Tail: 'T list
interface IEnumerable
interface IEnumerable<'T>
member Head : 'T
member IsEmpty : bool
member Item : index:int -> 'T with get
member Length : int
member Tail : 'T list
static member Cons : head:'T * tail:'T list -> 'T list
static member Empty : 'T list
Full name: Microsoft.FSharp.Collections.List<_>
val sum : list:'T list -> 'T (requires member ( + ) and member get_Zero)
Full name: Microsoft.FSharp.Collections.List.sum
val printfn : format:Printf.TextWriterFormat<'T> -> 'T
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
val square : x:int -> int
Full name: Document.square
val x : int
val sq : int
Full name: Document.sq
type Person =
{First: string;
Last: string;}
Full name: Document.Person
Person.First: string
Multiple items
val string : value:'T -> string
Full name: Microsoft.FSharp.Core.Operators.string
--------------------
type string = System.String
Full name: Microsoft.FSharp.Core.string
Person.Last: string
type Employee =
| Worker of Person
| Manager of Employee list
Full name: Document.Employee
union case Employee.Worker: Person -> Employee
union case Employee.Manager: Employee list -> Employee
type 'T list = List<'T>
Full name: Microsoft.FSharp.Collections.list<_>
val triple : x:int -> int
Full name: Document.triple
val tripleSquared : (int -> int)
Full name: Document.tripleSquared
val fibonacci : n:int -> int
Full name: Document.fibonacci
val n : int
val unlockAchievement : gameObject:'a -> achivement:'b -> unit
Full name: Document.unlockAchievement
val gameObject : 'a
val achivement : 'b
val character : obj
val not : value:bool -> bool
Full name: Microsoft.FSharp.Core.Operators.not
val keyboard : 'a
active recognizer SpaceKey: 'a -> 'b
Full name: Document.( |SpaceKey| )
active recognizer Hold100ms: 'a -> 'b
Full name: Document.( |Hold100ms| )
namespace System
Multiple items
val int : value:'T -> int (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.int
--------------------
type int = int32
Full name: Microsoft.FSharp.Core.int
--------------------
type int<'Measure> = int
Full name: Microsoft.FSharp.Core.int<_>
Functional Programming in games ... with F#
Andrea Magnorsky @ Digital Dragons
Digital Furnace Games ▀ BatCat Games ▀ GameCraft Foundation
Working on OniKira: Demon Killer
Available on Steam Early Access
Working on OniKira: Demon Killer
Steam Early Access
Complexity causes
- State
- Flow of control
- Code volume
With Lisp, one can rapidly develop meta constructs for behaviors and combine them in new ways. In addition, Lisp allows the redefinition of the language to easily add new constructs; particularly those needed to deal with time-based behaviors and layering of actions....
Contrary to popular belief, there is nothing inherently slow about Lisp. It is easy to construct a simple dialect which is just as efficient as C, but retains the dynamic and consistent qualities that make Lisp a much more effective expression of one’s programming intentions.
Andy Gavin, Naughty Dog co-founder Sauce
So we tried F#
- Functional first
- .net Interop
- Type system
- OSS
- Cross platform
- Divine learning curve
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
|
// one-liners
[1..100] |> List.sum |> printfn "sum=%d"
// no curly braces, semicolons or parentheses
let square x = x * x
let sq = square 42
// simple types in one line
type Person = {First:string; Last:string}
// complex types in a few lines
type Employee =
| Worker of Person
| Manager of Employee list
let square x = x * x
let triple x = x * 3
let tripleSquared = square >> triple
|
Visit F# for Fun and Profit for more examples and knowledge
What we use

1:
2:
3:
4:
5:
|
let rec fibonacci n =
match n with
| 0 -> 0
| 1 -> 1
| _ -> fibonacci (n - 1) + fibonacci (n - 2)
|
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
|
let unlockAchievement gameObject achivement=
match gameObject.GetComponent<CharacterController>() with
| null -> ()
| character ->
if (not character.IsOnGround()) then
PlatformHelper.UnlockAchievement achivement
this.GameObj.GetComponent<ScriptComponent>().DisposeLater()
match msg with
| :? ActorDiedMessage as diedMessage ->
unlockAchievement diedMessage.GameObj GameAchivement.AirKill
| _ -> ()
|
Active Patterns

1:
2:
3:
4:
5:
6:
7:
8:
9:
|
let (|SpaceKey|) (keyboard:KeyboardInput) =
keyboard.KeyPressed(Key.Space)
let (|Hold100ms|) (keyboard:KeyboardInput) =
keyboard.KeyPressedFor(Key.I, 100)
match DualityApp.Keyboard with
| SpaceKey true & Hold100ms false -> playerGo Jump
| SpaceKey true & Hold100ms true -> playerGo DoubleJump
|
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
|
let (|LeftKey|RightKey|OtherKey|) (keyboard:KeyboardInput) =
if keyboard.KeyPressed(Key.Left) then LeftKey
elif keyboard.KeyPressed(Key.Right) then RightKey
else OtherKey "Hi, you pressed a key...well that is interesting :D"
interface ICmpUpdatable with
member this.OnUpdate()=
match DualityApp.Keyboard with
| LeftKey -> playerGo Left
| RightKey-> playerGo Right
| OtherKey s-> ()
|
Interop
Check out the design guidelines
C# consuming F# code
Use namespaces in F# or prefix with global::YourModuleName
using System;
class Program
{
static void Main(string[] args)
{
var s = Calculator.Calc.add("4 4", "+");
Console.WriteLine("The sum is {0}", s);
}
} |
and the F# side
1:
2:
3:
4:
5:
6:
|
namespace Calculator
module Calc =
open System
let add numbers delimiter =
// Do stuff to add numbers
|
F# consuming C# code
1:
2:
3:
4:
5:
6:
|
module MathTest =
open NUnit.Framework
let [<Test>] ``2 + 2 should equal 4``() =
Assert.AreEqual(2 + 2, 4)
|
REPL
Now: exploration
Future: Live coding
Ecosystem: What we use now
- FsCheck
- Fake
- Compiler Services
Property Testing with FsCheck
Why write tests, when you can generate them
What is a property?
x + x = 2 * x
or
List.rev(List.rev list) = list
FsCheck
- QuickCheck paper by Koen Claessen and John Hughes
- Superb article by Scott Wlaschin on Property based testing .
- Can be used from C#
- Small library
- Can run stand alone or integrates with NUnit and xUnit
1:
2:
3:
|
[<Property>]
let ``When adding x to x then result is double x``(x:int)=
x + x = 2*x
|
1:
2:
3:
4:
5:
6:
7:
8:
|
let preconditionMaxHealth maxHealth = maxHealth > 0
[<Property(Verbose = true)>]
let ``Health should never be higher than max`` (x:int)(maxHealth:int)=
let healthComponent = initedHealth
healthComponent.MaxHealth <- maxHealth
healthComponent.IncreaseHealth x
preconditionMaxHealth maxHealth ==> (healthComponent.MaxHealth >= healthComponent.Health)
|
Fake : F# Make
- Use from any .net language
- It's mature.
- Builds for .net and mono, it's cross platform.
- No need to know F# to use it.
- Integrates with CI Server.
Hello world!
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
|
// include Fake lib
#r @"tools\FAKE\tools\FakeLib.dll"
open Fake
Target "Foo" (fun _ ->
trace "Hello World from Foo"
)
Target "Bar" (fun _ ->
trace "Hello World from Bar"
)
"Bar"
==> "Foo"
RunTargetOrDefault "Foo"
|
Compiler.Services
Use compiler service to compile a file into an assembly that is inmediately consumed by the game engine Duality.
Duality.Scripting
- File watcher
- Code in any editor :)
- Compiler Services call to fsc
- Future -> live coding
repo
Books
- Expert F#
- Programming F#
- Real World Functional programming
- More Books
Events
- User groups

Thanks :D
