F# IN THE ENTERPRISE Phillip Trelford @ptrelford Developer South Coast 2013
May 06, 2015
F# IN THE ENTERPRISE
Phillip Trelford@ptrelfordDeveloper South Coast2013
F#UNCTIONAL LONDONERS
570 Members
Founded 2010
Meets every 2 weeks
JOULE TRADING SCREEN
TESTIMONIALS F# in the Enterprise
F# FOR PROFIT
Time to Market
Efficiency
Correctness
Complexity
* applied to Analytic components
TIME TO MARKET
speed development by 50 percent or more,
European IB
order of magnitude increase in productivity,
GameSys
EFFICIENCY
processes that used to require hours now take just minutes, Grange Insurance
performance is 10× better than the C++ that it replaces, Aviva
CORRECTNESS
leads to virtually bug-free code,
Fixed Income
I am still waiting for the first bug to come in,
E-On
COMPLEXITY
everything becomes simple and clear when expressed in F#, Byron Cook
C# & F# BEST FRIENDS FOREVER Kaggle Testimonial
The fact that F# targets the CLR was also critical - even though we have a large existing code base in C#, getting started with F# was an easy decision because we knew we could use new modules right away.
TEST & INTEGRATION F# in the Enterprise
DEFECT RATE
I am both a C# dev and an F# dev. I can only offer subjective anecdotal evidence based on my experience of delivering projects in both languages (I am too busy delivering software to do anything else).
That said, the one stat in the summary that I find most compelling is the defect rate. I have now delivered three business critical projects written in F#. I am still waiting for the first bug to come in.
Simon Cousins, Power Company
DEPENDENCY INJECTION
F#
type VerySimpleStockTraderImpl
(analysisService:IStockAnalysisService,
brokerageService:IOnlineBrokerageService) =
interface IAutomatedStockTrader with
member this.ExecuteTrades() =
() // ...
C#
public class VerySimpleStockTraderImpl : IAutomatedStockTrader{ private readonly IStockAnalysisService analysisService; private readonly IOnlineBrokerageService brokerageService;
public VerySimpleStockTraderImpl( IStockAnalysisService analysisService, IOnlineBrokerageService brokerageService) { this.analysisService = analysisService; this.brokerageService = brokerageService; }
public void ExecuteTrades() { // ... }}
NUNIT
F# NUnit
module MathTest
open NUnit.Framework
let [<Test>] ``2 + 2 should equal 4``() = Assert.AreEqual(2 + 2, 4)
C# NUnit
using NUnit.Framework;
[TestFixture]public class MathTest{ [Test] public void TwoPlusTwoShouldEqualFour() { Assert.AreEqual(2 + 2, 4); }}
FSUNIT
[<Test>]let ``2 + 2 should equal 4``() = 2 + 2 |> should equal 4
UNQUOTE
let [<Test>] ``2 + 2 = 4``() = test <@ 2 + 2 = 4 @>
FSCHECK
.NET MOCKING LIBRARY
type ITime = abstract GetHour : unit -> int
type ImageCalculator (time:ITime) = member this.GetImageForTimeOfDay() = let hour = time.GetHour() if hour > 6 && hour < 21 then "sun.jpg" else "moon.jpg"
let [<Test>] `` at 01:00 the moon image should show `` () = let time = Mock().Setup(fun (x:ITime) -> x.GetHour()).Returns(1) let calculator = ImageCalculator(time.Create()) let image = calculator.GetImageForTimeOfDay() Assert.AreEqual("moon.jpg", image)
F# OBJECT EXPRESSION
type ITime = abstract GetHour : unit -> int
type ImageCalculator (time:ITime) = member this.GetImageForTimeOfDay() = let hour = time.GetHour() if hour > 6 && hour < 21 then "sun.jpg" else "moon.jpg“
let [<Test>] ``at 01:00 the moon image should show`` () = let time = { new ITime with member mock.GetHour() = 01 } let calculator = ImageCalculator(time) let image = calculator.GetImageForTimeOfDay() Assert.AreEqual("moon.jpg", image)
HIGHER-ORDER FUNCTION
let imageCalculator getHour = fun () -> let hour = getHour() if hour > 6 && hour < 21 then "sun.jpg" else "moon.jpg"
let [<Test>] ``at 01:00 the moon image should show`` () = let getHour () = 01 let getImageForHourOfDay = imageCalculator getHour let image = getImageForHourOfDay () Assert.AreEqual("moon.jpg", image)
MOCKING
F# Foq
let ``order sends mail if unfilled``() = // setup data let order = Order("TALISKER", 51) let mailer = mock() order.SetMailer(mailer) // exercise order.Fill(mock()) // verify verify <@ mailer.Send(any()) @> once
C# Moq
public void OrderSendsMailIfUnfilled(){ // setup data var order = new Order("TALISKER", 51); var mailer = new Mock<MailService>(); order.SetMailer(mailer.Object); // exercise order.Fill(Mock.Of<Warehouse>()); // verify mailer.Verify(mock => mock.Send(It.IsAny<string>()), Times.Once());}
CONTINUOUS BUILD
DSLS F# in the Enterprise
TICKSPEC
TICKSPEC OXO EXAMPLE
CELLZtype formula =
| Neg of formula
| Exp of formula * formula
| ArithmeticOp of
formula * arithmetic * formula
| LogicalOp of
formula * logical * formula
| Num of UnitValue
| Ref of int * int
| Range of int * int * int * int
| Fun of string * formula list
F# PROJECTS F# in the Enterprise
FILE ORDERING
MUTUAL RECURSION
type Folder(path:string) =
let files = Directory.GetFiles(path)
member folder.Files =
[|for file in files -> File(file,folder)|]
and File(filename: string, folder: Folder) =
member file.Name = filename
member file.Folder = folder
CYCLES
TickSpec (F#) SpecFlow (C#)
C#/F# INTEROP F# in the Enterprise
C#/F# INTEROP
Mostly it just works
Minor friction points
Equality
Explicit interfaces
Tuples & Union Types
Nulls
Tip: Read the F# Component Design Guidelines
EQUALITY: POP QUIZ
C# F#
var a =
new Order(Side.Bid, 99.9M, 5);
var b =
new Order(Side.Bid, 99.9M, 5);
return a == b;
let a = Order(Bid, 99.9M, 5)
let b = Order(Bid, 99.9M, 5)
a = b
F# REFERENCE EQUALITY
let (==) a b = obj.ReferenceEquals(a,b)
C# ==
public static bool operator == (Order a, Order b)
{
return a.Equals(b);
}
public static bool operator != (Person a, Person b)
{
return !a.Equals(b);
}
F# -> C# ==
static member op_Equality (a:Order,b:Order) =
a = b
static member op_Inequality (a:Order,b:Order) =
a <> b
OPERATORS F# in the Enterprise
OPERATORS
Brackets
List.reduce (+)
(List.map abs
[-9..+9])
Pipes
[-9..+9]
|> List.map abs
|> List.reduce (+)
SCALA: PIMP MY LIBRARY
F# GUIDELINES
http://fsharp.org/about/files/guidelines.pdf
CONCURRENCY F# in the Enterprise
IMMUTABILITY BY DEFAULT
Types
Tuples
Records
Discriminated Unions
Data structures
List
Map
Set
ASYNC WORKFLOWS
async {
do! control.MouseLeftButtonDown // First class events
|> Async.AwaitEvent
}
TYPE PROVIDERS F# in the Enterprise
TYPE PROVIDERS
WEB
B-MOVIE MADNESS
FUNSCRIPT
TRY F#: HTTP://TRYFSHARP.ORG
LEARN ME AN F# FOR GREAT GOOD
F# in the Enterprise
LEARNING F#
Hands on:
F# Koans
Katas/Project Euler
Reading:
F# for Fun and Profit
Podcasts:
.Net Rocks
F# BOOKS
SHOW ME THE MONEY!
QUESTIONS?
Twitter:
@ptrelford
Blog: http://trelford.com/blog
Foundation: http://fsharp.org