SlideShare a Scribd company logo
#dotNETSpain2015
Alfonso García-Caro
@alfonsogcn
github.com/alfonsogarciacaro/dotNetSpain2015
Functional Programming
in C# and F#
.NET Conference 2015
Y
A
X B
#dotNETSpain2015#dotNETSpain2015
Software Engineer at Green Eagle Solutions
.Net and Web developer
Collaborator of FunScript project
Organizer of Madrid .Net and F# Meetups
About me
#dotNETSpain2015#dotNETSpain2015
Personal view of functional programming
Every language and every programmer understands functional
programming a bit differently. There will also be some simplifications.
Bias towards F# but I also love C#
The sentence that will repeat most in this talk:
“possible in C#, idiomatic in F#”
Not an utilitarian-only approach
Like: “Immutability is good because makes parallelism easier”
...but won't bore you with tough Maths
If only because I wouldn't be able to.
Disclaimer
#dotNETSpain2015#dotNETSpain2015
Juan Pedro Villa Isaza, Category Theory
applied to Functional Programming
[…] we are considering the objects and morphisms of Set to be the sets of
all sets and all functions, respectively, which would lead to a paradox such
as the set of all sets not members of themselves. For this reason, we ought
to assume, for instance, that there is a big enough set, the universe, and
take the objects of Set to be the sets which are members of the universe,
that is, small sets. However, we shall not go into detail about mathematical
foundations of category theory(*).
(*) Thank goodness!
Can functional really help me?
#dotNETSpain2015#dotNETSpain2015
My boss, at the office
Download real-time market price data from the internet at periodical
intervals, insert it into the database and throw an event if the next hour
price is lower than the threshold. In that case, communicate with the
SCADA system through the OPC protocol to stop the wind turbines and
check if the response has been successful.
Is there really anyway the former can help
me with the latter?
Can functional really help me?
#dotNETSpain2015#dotNETSpain2015
We all use Math to write performant code
Yes, those algorithms you copy from StackOverflow are Math ;)
Functional uses Math to organize your code
Or as others like to say, to reason about your code.
Two main topics...
Alonzo Church's Lambda Calculus
Category Theory
What is functional programming?
#dotNETSpain2015
Lambda Calculus
It's the composability, ***
#dotNETSpain2015#dotNETSpain2015
Turing revisited
Only three rules to express all possible computations
(e stands for expression)
Examples of lambdas:
e ::= x Reference Func<int, int> f = x => x + x; // C#
| λx.e Definition let f x = x + x // F#
| e e Application let f' = fun x -> x + x // F#
Wait, there is reference but no assignment?
In strict functional there's no assignment, only binding.
Binding is the same as definition an application at once.
There's no re-binding either, and thus mutability is an alien concept.
Alonzo Church's Lambda Calculus
Binding
int add5(int x) {
var five = 5; // Assigning a variable in local scope
return x + five; // and performing a computation with it...
}
int add5_(int x) {
Func<int, int> f = five => x + five; // ...is the same as defining a function
return f(5); // and applying it
}
int add5__(int x) {
var five = 5; // Look again: this is the parameter
return x + five; // and this is the body of the function
}
let add5 x =
let five = 5 // Now in F#
x + five // These three blocks are identical
let add5' x =
(fun five -> x + five)(5) // Definition and application
let add5'' x =
let five = 5 in // With the verbose syntax, you can see
x + five // the body of the binding more easily
let add5''' x =
let five = 5 // Error: binding body missing (in local scope)
#dotNETSpain2015#dotNETSpain2015
Q. Is this not a limitation to the expressiveness of the language?
A. Maybe, but if you look around you'll see that this design pattern is very
common in nature.
Fractal theory
Complex design emerge from simple patterns.
Every element has very few dependencies.
Same structure at all levels: expression < function < module/file < library
Why few rules is a good thing?
Fractals in nature
#dotNETSpain2015#dotNETSpain2015
Lambda Calculus uses only expressions
Did you notice statements were also missing in Alonzo's rules?
Statements are like void functions
They don't return a value, thus they only can have an influence in your
program through side-effects.
Statements are everywhere
Variable declaration
Conditionals: if/else, switch
Loops: for, do, while
Exception: try/catch
Scope: using
Void functions: I/O, state
Expressions vs Statements
Program flow
This is how the program flow looks
with staments.
Notice there's no return arrow.
“Well, it doesn't look so bad”
Really?
Let's see it with side-effects.
Program flow
Side-effects break encapsulation.
Diagrams cannot be accurately
represented with statements.
Side-effects depend on mutable
state for every minor action (loops).
Alternatives to statements
Conditionals → ?: operator
Switch → Pattern Matching
Loops → LINQ, recursion
Exceptions → Monads
#dotNETSpain2015#dotNETSpain2015
Natural flow
Fluent APIs (e.g. LINQ) use expressions to chain operations naturally.
Code readability is improved (see next page: visual honesty).
Branching
Techniques like pattern matching allow natural branching of the code.
The Abstract Syntax Tree (AST) builds naturally.
Diagrams can be represented more accurately.
Pure functions
Strict functional only allows pure functions.
Pure functions always return a value and don't have side-effects.
They don't break the program flow.
Expression merits
Visual Honesty with Fluent APIs
Source: www.theburningmonk.com
Pattern Matching
The feature that sacrificed itself so
C# 6.0 could be released on time
Pattern Matching
Switch on steroids
Pattern Matching
// With some effort you can still get switch expressions in C#
enum Pet { Dog, Cat, Bird }
static class Extensions {
public static T Switch<T>(this Pet pet, Func<T> dog, Func<T> cat, Func<T> bird)
{
switch (pet) {
case Pet.Dog: return dog();
case Pet.Cat: return cat();
case Pet.Bird: return bird();
default:
throw new Exception("Inexhaustive matching");
}
}
}
class Program {
public int HowOldIsMyPet(int animalYears, Pet pet) {
return pet.Switch(
dog: () => animalYears * DOG_YEARS,
cat: () => animalYears * CAT_YEARS,
bird:() => animalYears * BIRD_YEARS
);
}
}
Pattern Matching
// Or even Union Types (aka Sum or Algebraic Types)
public abstract class Option<T>
{
public readonly T Value;
Option() { }
Option(T value) { Value = value; }
public sealed class Some : Option<T> {
public Some(T value) : base(value) { }
}
public sealed class None : Option<T> {
public None() : base() { }
}
public TOutput Match<TOutput>(Func<T, TOutput> some, Func<TOutput> none) {
return this is Some ? some(Value) : none();
}
}
class Program {
public Option<string> foo() {
return new Option<string>.Some("Foo!");
}
public string bar() {
return foo().Match(
some: name => "FOUND: " + name,
none: () => "NOTHING");
}
}
Pattern Matching
// In F# these constructs are idiomatic and the syntax is much terser
// Most of the times we use union types with Pattern Matching
// Union types look like enum, but they can actually contain any value
// We can extract this value when pattern matching
type Pet =
| Dog of int
| Cat of int
| Bird of int
let howOldIsMyPet pet years =
match pet with
| Dog dy -> years * dy
| Cat cy -> years * cy
| Bird by -> years * by
// Dummy methods
let riskyFn(): int option = failwith "Not implemented"
let doSth(i: int): unit = failwith "Not implemented"
// Option type is a particular union type and it's built-in
let main() =
match riskyFn() with
| Some i -> doSth i
| None -> ()
Syntax Trees are also in Nature
#dotNETSpain2015
Category Theory
Road to Monads
Road to perdition?
#dotNETSpain2015#dotNETSpain2015
You're already using monads
LINQ and Task are also monads. Sort of.
If I already use them, do I need the theory?
Think of it as the garbage collector, when you try to learn a bit about it,
you can use it more efficiently.
But, what is category anyway?
Is it not the same as a set?
Good news! (maybe)
#dotNETSpain2015#dotNETSpain2015
A collection with three components
A collection of objects
A collection of morphisms
Composition of the morphisms, which must be associative
How do they map to C#/F#?
Objects are types (Attention!)
Morphisms are functions
In F#, composition is the >> operator
(f >> g)(x) = f(g(x))
In C#, composition is often represented with fluent APIs
Task.Run(() => foo())
.ContinueWith(x => bar(x))
What is a category?
#dotNETSpain2015#dotNETSpain2015
CT provides us with a formal language
If the program needs to be deterministic, we need a deterministic way to
think about it.
Obeying the laws it dictates can give us a proof of correctness.
More practically, we can generate random tests to check whether the
expected properties of our types are being fulfilled (FSCheck).
CT teaches us about transformations
If our types and functions (categories) follow certain laws, we know we can
apply some specific transformations.
This is great, because there are many categories following these rules
which we are not usually aware of.
We are going to consider these categories as contexts as in non-
deterministic, sequential or asynchronous contexts.
What is Category Theory useful for?
#dotNETSpain2015#dotNETSpain2015
Functors map one category into another
It could be represented as an interface like this (pseudo code):
F<a> Map<F,a,b>(this F<a> input, Func<a,b> f) // C#
map: ('a → 'b) → 'F<'a> → 'F<'b> // F#
The Functor must follow these rules:
F(id a) = id(F a) // identity
F(f >> g) = F(f) >> F(g) // composition
Attention! The language doesn't enforce these rules, we must check them
ourselves... but this is usually a work for library writers :)
The .NET type system doesn't allow this signature. However many contexts
(say, generic types) implement it. Do you recognize it?
Our first transformation: the Functor
Functors in C# and F#
public static Task<TOutput> Select<T, TOutput>(this Task<T> input, Func<T, TOutput> f) {
return input.ContinueWith(t => f(t.Result));
}
public static Nullable<TOutput> Select<T, TOutput>(this Nullable<T> input, Func<T, TOutput> f)
where TOutput : struct {
return input.HasValue
? new Nullable<TOutput>(f(input.Value))
: new Nullable<TOutput>();
}
myList.Select(x => x + x); // Sequential context
myTask.Select(x => x + x); // Asynchronous context
myNullable.Select(x => x + x); // Non-deterministic context
// In F#, most contexts implement the map function
// Instead of extension methods we often use module-bound functions
type Async<'a> with
static member map f x = async { let! y = x in return f y }
let myList = [1; 2; 3;]
let myOption: Option<int> = None // Option is preferred over Nullable
let myAsync: Async<int> = async { return 1 } // Async is prererred over Task
List.map (fun x -> x + x) myList // Functions can be chained with |> or >>
Option.map (fun x -> x + x) myOption // myList |> List.map f |> List.map f'
Async.map (fun x -> x + x) myAsync // List.map (f >> g) myList
#dotNETSpain2015#dotNETSpain2015
Abstraction is one pillar of functional
Everybody wants to program in a synchronous, deterministic context.
We don't need to worry about the implementation details of translating
our computation to the context, the library does it for us.
This is may be trivial in certain contexts (IEnumerable, Nullable) but not in
others (concurrent and parallel programming). The garbage collector for
example has been abstracting the context of heap memory for years.
Abstraction favors composability
We can apply the same functions to different context or, at least, the same
programming style.
Why abstract the context?
#dotNETSpain2015#dotNETSpain2015
What if we want to combine several
contexts?
With map we can only apply a computation to a specific context.
Sometimes we need to apply a function to several contexts at once. For
example if we need to check all nullable fields of a UI form.
Then we need to move one step further and see Applicative Functors.
But before that we need to tackle another topic...
Partial applications
When mapping is not enough
#dotNETSpain2015#dotNETSpain2015
Pure functions only take one argument
For example, when we see a function like this in F#:
let f x y = x + y
(We can also pass tuples, but let's focus on partial application no.)
It would translate to C# like:
Func<int, Func<int, int>> f = x => y => x + y;
This way, if we apply only one argument we get a partially applied function:
var add5 = f(5); // add5 == x => x + 5;
Why would we need that?
Composability, remember?
Anyway, with this knowledge we can keep on.
Partial applications
Applicative Functors in C#
// First lift the curried function to the domain of the context
public static IEnumerable<a> Pure<a>(a input) {
return new a[] { input };
}
// Then apply the function to the first operand. As the result is a partially applied
// function, we can still apply it to the rest of the operands
public static IEnumerable<b> Apply<a, b>(IEnumerable<Func<a, b>> liftedFn, IEnumerable<a> input)
{
foreach (var f in liftedFn)
foreach (var x in input)
yield return f(x);
}
// Test
Func<int, Func<int, int>> add = x => y => x + y;
var lifted1 = Pure(add);
var lifted2 = Apply(lifted1, new int[] { 1, 2 } );
Apply(lifted2, new int[] { 3, 4 }); // Output: 4, 5, 5, 6
Applicative Functors in C#
public static partial class Option {
public static Option<a> Pure<a>(a input) {
return new Option<a>.Some(input);
}
public static Option<b> Apply<a, b>(Option<Func<a, b>> liftedFn, Option<a> input) {
return liftedFn.Match(
some: f => Option.Map(input, f),
none: () => new Option<b>.None()
);
}
}
public static partial class Async {
public static Task<a> Pure<a>(a input) {
return Task.Run(() => input);
}
/// <summary>Caution: Simplified code, no error nor cancellation checks</summary>
public static Task<b> Apply<a, b>(Task<Func<a, b>> liftedFn, Task<a> input) {
var tcs = new TaskCompletionSource<b>();
liftedFn.ContinueWith(f =>
input.ContinueWith(x =>
tcs.SetResult(f.Result(x.Result))
));
return tcs.Task;
}
}
Applicative Functors in C#
// Downloading several web pages using the Applicative Functor
var downloader = new WebPageDownloader();
Func<string, Task<string>> fetch10 =
url => downloader.FetchLinesAsync(url, 10);
Func<string, Func<string, Func<string, string>>> curry =
x => y => z => x + y + z;
var res1 = await
Async.Apply(
Async.Apply(
Async.Apply(
Async.Pure(curry),
fetch10("http://microsoft.github.io")),
fetch10("http://fsharp.org")),
fetch10("http://funscript.info")
);
// Obviously, the syntax is not very pretty.
// We can simplify it by providing methods to lift
// functions with a fixed number of arguments.
// Like...
Applicative Functors in C#
public static partial class Async {
// We can take the chance to add some optimizations (like parallelism)
// But let's keep it simple for now
public static Task<e> Lift3<a, b, c, e>(Func<a, b, c, e> f, Task<a> x, Task<b> y, Task<c> z){
Func<a, Func<b, Func<c, e>>> curry =
_x => _y => _z => f(_x, _y, _z);
var lifted1 = Pure(curry);
var lifted2 = Apply(lifted1, x);
var lifted3 = Apply(lifted2, y);
return Apply(lifted3, z);
}
}
// Now the previous code can be rewritten as:
await Async.Lift3(
(x,y,z) => x+y+z,
fetch10("http://microsoft.github.io"),
fetch10("http://fsharp.org"),
fetch10("http://funscript.info")
);
#dotNETSpain2015#dotNETSpain2015
Source: http://www.slideshare.net/ScottWlaschin/
Lifting is not only for Hollywood
stars
Applicative Functors in F#
// In F#, thanks to type inference and other features the syntax is much terser
// Also, many of the functions we need are already implemented
// We can define our custom operators for an even lighter syntax too
module Seq =
let ``pure`` f = seq { yield f } // pure is a keyword in F#
let (<*>) f a = // <*> is often used for applying
seq { for f in f do
for a in a do
yield f a }
let (<!>) f a = ``pure`` f <*> a // Convenience operator
let f x y = x + y // Quick tests
printfn "%A" (f <!> [3;4] <*> [2;1])
printfn "%A" (f <!> [3;4] <*> [])
module Option =
let (<*>) f a =
match f with
| Some f -> Option.map f a
| None -> None
let ``pure`` f = Some f
let (<!>) f a = ``pure`` f <*> a
printfn "%A" ((+) <!> Some 5 <*> Some 4) // Quick tests
printfn "%A" ((+) <!> Some 5 <*> None )
Applicative Functors in F#
module Async =
let ``pure`` f = async { return f }
let (<*>) f a = async { let! f = f
let! a = a
return f a }
let (<!>) f a = ``pure`` f <*> a
// Downloading content from the internet
let fetchLines (url: string) i = async {
let rec append i (s: StreamReader) (b: StringBuilder) =
match i with
| 0 -> b.ToString()
| _ -> s.ReadLine() |> b.AppendLine |> append (i-1) s
let req = WebRequest.Create(url)
use! resp = req.AsyncGetResponse()
use stream = resp.GetResponseStream()
use reader = new StreamReader(stream)
return append i reader (StringBuilder()) }
(fun x y z -> String.length x + String.length y + String.length z)
<!> fetchLines "http://microsoft.github.io" 10
<*> fetchLines "http://fsharp.org" 10
<*> fetchLines "http://funscript.info" 10
|> Async.RunSynchronously
|> printfn "Chars fetched: %i"
#dotNETSpain2015#dotNETSpain2015
What's a monad anyway?
A monad is a monoid in the category of endofunctors, what's the problem?
http://james-iry.blogspot.com.es/2009/05/brief-incomplete-and-mostly-
wrong.html
What's a monad useful for?
We've just seen how to lift a function so it can be applied to operands
“wrapped” in a context. However, there are many cases when we want to
unwrap an operand and return a result already in the context. Think of:
Sequential → Extract an element from a collection and return a collection
(LINQ SelectMany())
Non-deterministic → Extract the value of Nullable, Option, Either and
return the result of a risky operation
Async → Extract the result of an asynchronous operation and perform
another asynchronous operation
Monad is coming
#dotNETSpain2015#dotNETSpain2015
So we need a transformation with the following signature:
M<a> Return<a>(a input) // Same as Pure in Applicatives
M<b> Bind<a,b>(M<a> input, Func<a,M<b>> f)
return: 'a → 'M<'a>
bind: 'a → ('M<'a> → 'M<'b>) → 'M<'b>
The return function is used to “leave the monad.”
As monadic expressions are just abstract computations that we need later
to apply into a context, the return value must be wrapped in the context.
Thus, we have to “wrap” the result before leaving the monad.
(Depending on how the language implements the concept of monad, we
may need to implement other functions. But let's ignore them for now.)
Mapping vs Binding
Monads in C#
public static partial class Seq {
public static IEnumerable<a> Return<a>(a input) { return Pure(input); }
public static IEnumerable<b> Bind<a, b>(IEnumerable<a> input, Func<a, IEnumerable<b>> f) {
return input.SelectMany<a, b>(f);
}
}
public static partial class Option {
public static Option<a> Return<a>(a input) { return Pure(input); }
public static Option<b> Bind<a, b>(Option<a> input, Func<a, Option<b>> f) {
return input.Match(
some: v => f(v),
none: () => new Option<b>.None()
);
}
}
public static partial class Async {
public static Task<a> Return<a>(a input) { return Pure(input); }
/// <summary>Caution: Simplified code, no error nor cancellation checks</summary>
public static Task<b> Bind<a, b>(Task<a> input, Func<a, Task<b>> f) {
var tcs = new TaskCompletionSource<b>();
input.ContinueWith(x =>
f(x.Result).ContinueWith(y =>
tcs.SetResult(y.Result)));
return tcs.Task;
}
Monads in F#
module Seq =
let ``return`` f =
seq { yield f }
let (>>=) xs f = // This is the usual operator for bind
seq { for x in xs do
yield! f x }
module Option =
let ``return`` f = Some f
// Already implemented in FShap.Core
let (>>=) a f =
match a with
| Some a -> f a
| None -> None
module Async =
// Already implemented in FShap.Core
let ``return`` = async.Return
let (>>=) a f = async.Bind(a, f)
And this is how we use them
var downloader = new WebPageDownloader(); // C#
Func<string, Task<string>> fetch10 =
url => downloader.FetchLinesAsync(url, 10);
var res1 = await Async.Bind(
fetch10("http://microsoft.github.io"),
x => Async.Bind(
fetch10("http://fsharp.org"),
y => Async.Bind(
fetch10("http://funscript.info"),
z => Async.Return(x + y + z)
)
)
);
let fetchLines (url: string) i = async { // F#
let rec append i (s: StreamReader) (b: StringBuilder) =
match i with
| 0 -> b.ToString()
| _ -> s.ReadLine()
|> b.AppendLine
|> append (i-1) s
let req = WebRequest.Create(url)
use! resp = req.AsyncGetResponse()
use stream = resp.GetResponseStream()
use reader = new StreamReader(stream)
return append i reader (StringBuilder())}
async.Bind(fetchLines "http://microsoft.github.io" 10, fun x ->
async.Bind(fetchLines "http://fsharp.org" 10, fun y ->
async.Bind(fetchLines "http://funscript.info" 10, fun z ->
async.Return(x + y + z))))
|> Async.RunSynchronously
#dotNETSpain2015#dotNETSpain2015
Is this any advance at all?
Monads can be really useful, but nesting function is not pretty and soon
leads to “callback hell.”
That's why most languages implementing monads add a macro system
(sugar syntax) in order to make them more pleasant.
In C# we can use extension methods or even abuse the LINQ special
syntax.
In F# we have computation expressions, designed for monads but
including also many extra features:
Generators seq { for x in xs do yield x + x }
Query expressions query { from x in db do select x }
Macros for .NET constructs use!
But this is horrible!
Monads revisited
// Extension method to use LINQ syntax with Task
public static Task<b> Select<a, b>(this Task<a> input, Func<a, b> f) {
return Async.Map(input, f);
}
public static Task<c> SelectMany<a,b,c>(
this Task<a> input, Func<a, Task<b>> f, Func<a, b, c> projection) {
return Bind(input, outer =>
Bind(f(outer), inner =>
Return(projection(outer, inner))));
}
// Now we can concatenate async operations using LINQ syntax
await (from x in fetch10("http://microsoft.github.io")
from y in fetch10("http://fsharp.org")
let url = "http://funscript.info"
from z in fetch10(url)
select x + y + z);
// In F# the boiler plate code has already been done for us in Async
// But we can implement our own custom computation expressions easily
async { let! x = fetchLines "http://microsoft.github.io" 10
let! y = fetchLines "http://fsharp.org" 10
let url = "http://funscript.info"
let! z = fetchLines url 10
return x + y + z }
|> Async.RunSynchronously
#dotNETSpain2015#dotNETSpain2015
Why monads seems to be some pervasive
in functional programming?
Why I don't hear to talk about functors or applicatives so much?
Monads are an elegant idea. Same as map/reduce they can be used to
deal in a similar fashion with many different problems.
In strict functional programming they have been used to tackle side-
effects, for example: IO, State monads
We can also use the F# Async monad to code state machines without
flags.
Feel the monad!
OK, I get the idea but...
State machines without state?
The state is in the program flow
#dotNETSpain2015
Now you're ready to join
the functional army!
#dotNETSpain2015#dotNETSpain2015
#dotNETSpain2015#dotNETSpain2015
http://ericlippert.com/2013/02/21/monads-part-one/
Monads and C#, by Eric Lippert
Real-World Functional Programming, with examples in F# and C#
By Tomas Petricek and Jon Skeet
http://fsharpforfunandprofit.com/
By Scott Wlaschin
The site to learn F# and functional programming, from an F# perspective
http://learnyouahaskell.com/
By Miran Lipovaca
A strict functional language helps you understand better the concepts
http://bugsquash.blogspot.com.es/
By Mauricio Scheffer
References

More Related Content

What's hot (20)

PDF
Top C Language Interview Questions and Answer
Vineet Kumar Saini
 
PPT
F# Intro for Scala Developers
fsug
 
PDF
Advanced C Language for Engineering
Vincenzo De Florio
 
PDF
Syntax analysis
Akshaya Arunan
 
PPTX
C languaGE UNIT-1
Malikireddy Bramhananda Reddy
 
PPT
C++ to java
Ajmal Ak
 
PPTX
C++ ppt
parpan34
 
PPTX
Python Introduction
vikram mahendra
 
PDF
FregeDay: Design and Implementation of the language (Ingo Wechsung)
Dierk König
 
PDF
Functional Programming - Worth the Effort
BoldRadius Solutions
 
PPTX
C Language (All Concept)
sachindane
 
PPTX
Top Down Parsing, Predictive Parsing
Tanzeela_Hussain
 
PPT
Basics of c++
Huba Akhtar
 
PPTX
Types of Parser
SomnathMore3
 
DOC
C notes diploma-ee-3rd-sem
Kavita Dagar
 
PDF
Learning c - An extensive guide to learn the C Language
Abhishek Dwivedi
 
PPT
Basics of C programming
avikdhupar
 
PDF
C programming notes
Prof. Dr. K. Adisesha
 
PPT
The smartpath information systems c pro
The Smartpath Information Systems,Bhilai,Durg,Chhattisgarh.
 
Top C Language Interview Questions and Answer
Vineet Kumar Saini
 
F# Intro for Scala Developers
fsug
 
Advanced C Language for Engineering
Vincenzo De Florio
 
Syntax analysis
Akshaya Arunan
 
C++ to java
Ajmal Ak
 
C++ ppt
parpan34
 
Python Introduction
vikram mahendra
 
FregeDay: Design and Implementation of the language (Ingo Wechsung)
Dierk König
 
Functional Programming - Worth the Effort
BoldRadius Solutions
 
C Language (All Concept)
sachindane
 
Top Down Parsing, Predictive Parsing
Tanzeela_Hussain
 
Basics of c++
Huba Akhtar
 
Types of Parser
SomnathMore3
 
C notes diploma-ee-3rd-sem
Kavita Dagar
 
Learning c - An extensive guide to learn the C Language
Abhishek Dwivedi
 
Basics of C programming
avikdhupar
 
C programming notes
Prof. Dr. K. Adisesha
 
The smartpath information systems c pro
The Smartpath Information Systems,Bhilai,Durg,Chhattisgarh.
 

Viewers also liked (20)

PPTX
Functional Programming with C#
EastBanc Tachnologies
 
PDF
Dr Frankenfunctor and the Monadster
Scott Wlaschin
 
PDF
Domain Driven Design with the F# type System -- NDC London 2013
Scott Wlaschin
 
PDF
[FT-11][ltchen] A Tale of Two Monads
Functional Thursday
 
PPTX
Building a game in a day
Phillip Trelford
 
PDF
Enterprise Tic-Tac-Toe
Scott Wlaschin
 
PDF
Railway Oriented Programming
Scott Wlaschin
 
PPTX
Why functional programming in C# & F#
Riccardo Terrell
 
PDF
Functional Programming Patterns (NDC London 2014)
Scott Wlaschin
 
PDF
Domain Driven Design with the F# type System -- F#unctional Londoners 2014
Scott Wlaschin
 
PPTX
Rx- Reactive Extensions for .NET
Jakub Malý
 
PDF
Matching Card Game Templates - Historical Places
Ryan Pecson
 
PDF
A Quick Intro to ReactiveX
Troy Miles
 
PPTX
Introduction to F#
Jonas Follesø
 
PPTX
Matching Game Mechanics and Human Computation Tasks in Games with a Purpose
Luca Galli
 
PDF
Instruments matching game
CEIP Juan XXIII
 
PPTX
New features in C# 6
Software Associates
 
PDF
Configuring SSL on NGNINX and less tricky servers
Axilis
 
PPTX
NuGet Must Haves for LINQ
Axilis
 
PPTX
Functional programming in C#
Thomas Jaskula
 
Functional Programming with C#
EastBanc Tachnologies
 
Dr Frankenfunctor and the Monadster
Scott Wlaschin
 
Domain Driven Design with the F# type System -- NDC London 2013
Scott Wlaschin
 
[FT-11][ltchen] A Tale of Two Monads
Functional Thursday
 
Building a game in a day
Phillip Trelford
 
Enterprise Tic-Tac-Toe
Scott Wlaschin
 
Railway Oriented Programming
Scott Wlaschin
 
Why functional programming in C# & F#
Riccardo Terrell
 
Functional Programming Patterns (NDC London 2014)
Scott Wlaschin
 
Domain Driven Design with the F# type System -- F#unctional Londoners 2014
Scott Wlaschin
 
Rx- Reactive Extensions for .NET
Jakub Malý
 
Matching Card Game Templates - Historical Places
Ryan Pecson
 
A Quick Intro to ReactiveX
Troy Miles
 
Introduction to F#
Jonas Follesø
 
Matching Game Mechanics and Human Computation Tasks in Games with a Purpose
Luca Galli
 
Instruments matching game
CEIP Juan XXIII
 
New features in C# 6
Software Associates
 
Configuring SSL on NGNINX and less tricky servers
Axilis
 
NuGet Must Haves for LINQ
Axilis
 
Functional programming in C#
Thomas Jaskula
 
Ad

Similar to Functional Programming in C# and F# (20)

PPTX
Intro f# functional_programming
Mauro Ghiani
 
PPTX
Functional programming with FSharp
Daniele Pozzobon
 
PPTX
Introduction to Functional Programming
Dave Fancher
 
PPTX
TechDaysNL 2015 - F# for C# Developers
Ronald Harmsen
 
PDF
Introduction to functional programming
Konrad Szydlo
 
PPTX
Real World F# - SDD 2015
Phillip Trelford
 
PPTX
A Skeptics guide to functional style javascript
jonathanfmills
 
PPTX
London F-Sharp User Group : Don Syme on F# - 09/09/2010
Skills Matter
 
PPTX
F# Eye 4 the C# Guy
Phillip Trelford
 
PDF
Functional Programming in F#
Dmitri Nesteruk
 
PPTX
Functional pogramming hl overview
Elad Avneri
 
PPTX
Intro to Functional Programming
Jordan Parmer
 
PDF
379008-rc217-functionalprogramming
Luis Atencio
 
PPTX
Functional programming
PiumiPerera7
 
PDF
Go Beyond Higher Order Functions: A Journey into Functional Programming
Lex Sheehan
 
PPTX
Столпы функционального программирования для адептов ООП, Николай Мозговой
Sigma Software
 
PPTX
Break Free with Managed Functional Programming: An Introduction to F#
Dave Fancher
 
PPTX
Break Free with Managed Functional Programming: An Introduction to F#
IndyMobileNetDev
 
PDF
Booting into functional programming
Dhaval Dalal
 
PPTX
Functional Programming in Swift
Saugat Gautam
 
Intro f# functional_programming
Mauro Ghiani
 
Functional programming with FSharp
Daniele Pozzobon
 
Introduction to Functional Programming
Dave Fancher
 
TechDaysNL 2015 - F# for C# Developers
Ronald Harmsen
 
Introduction to functional programming
Konrad Szydlo
 
Real World F# - SDD 2015
Phillip Trelford
 
A Skeptics guide to functional style javascript
jonathanfmills
 
London F-Sharp User Group : Don Syme on F# - 09/09/2010
Skills Matter
 
F# Eye 4 the C# Guy
Phillip Trelford
 
Functional Programming in F#
Dmitri Nesteruk
 
Functional pogramming hl overview
Elad Avneri
 
Intro to Functional Programming
Jordan Parmer
 
379008-rc217-functionalprogramming
Luis Atencio
 
Functional programming
PiumiPerera7
 
Go Beyond Higher Order Functions: A Journey into Functional Programming
Lex Sheehan
 
Столпы функционального программирования для адептов ООП, Николай Мозговой
Sigma Software
 
Break Free with Managed Functional Programming: An Introduction to F#
Dave Fancher
 
Break Free with Managed Functional Programming: An Introduction to F#
IndyMobileNetDev
 
Booting into functional programming
Dhaval Dalal
 
Functional Programming in Swift
Saugat Gautam
 
Ad

Recently uploaded (20)

PDF
Bitcoin for Millennials podcast with Bram, Power Laws of Bitcoin
Stephen Perrenod
 
DOCX
Python coding for beginners !! Start now!#
Rajni Bhardwaj Grover
 
PPTX
MuleSoft MCP Support (Model Context Protocol) and Use Case Demo
shyamraj55
 
PDF
Transcript: Book industry state of the nation 2025 - Tech Forum 2025
BookNet Canada
 
PDF
The Rise of AI and IoT in Mobile App Tech.pdf
IMG Global Infotech
 
PDF
Peak of Data & AI Encore AI-Enhanced Workflows for the Real World
Safe Software
 
PPTX
New ThousandEyes Product Innovations: Cisco Live June 2025
ThousandEyes
 
PDF
The 2025 InfraRed Report - Redpoint Ventures
Razin Mustafiz
 
PPTX
The Project Compass - GDG on Campus MSIT
dscmsitkol
 
PDF
What’s my job again? Slides from Mark Simos talk at 2025 Tampa BSides
Mark Simos
 
PDF
“Squinting Vision Pipelines: Detecting and Correcting Errors in Vision Models...
Edge AI and Vision Alliance
 
PDF
Mastering Financial Management in Direct Selling
Epixel MLM Software
 
PPTX
Designing_the_Future_AI_Driven_Product_Experiences_Across_Devices.pptx
presentifyai
 
PDF
Automating Feature Enrichment and Station Creation in Natural Gas Utility Net...
Safe Software
 
PDF
“NPU IP Hardware Shaped Through Software and Use-case Analysis,” a Presentati...
Edge AI and Vision Alliance
 
PDF
Newgen Beyond Frankenstein_Build vs Buy_Digital_version.pdf
darshakparmar
 
PPTX
AI Penetration Testing Essentials: A Cybersecurity Guide for 2025
defencerabbit Team
 
PDF
Transforming Utility Networks: Large-scale Data Migrations with FME
Safe Software
 
PPT
Ericsson LTE presentation SEMINAR 2010.ppt
npat3
 
DOCX
Cryptography Quiz: test your knowledge of this important security concept.
Rajni Bhardwaj Grover
 
Bitcoin for Millennials podcast with Bram, Power Laws of Bitcoin
Stephen Perrenod
 
Python coding for beginners !! Start now!#
Rajni Bhardwaj Grover
 
MuleSoft MCP Support (Model Context Protocol) and Use Case Demo
shyamraj55
 
Transcript: Book industry state of the nation 2025 - Tech Forum 2025
BookNet Canada
 
The Rise of AI and IoT in Mobile App Tech.pdf
IMG Global Infotech
 
Peak of Data & AI Encore AI-Enhanced Workflows for the Real World
Safe Software
 
New ThousandEyes Product Innovations: Cisco Live June 2025
ThousandEyes
 
The 2025 InfraRed Report - Redpoint Ventures
Razin Mustafiz
 
The Project Compass - GDG on Campus MSIT
dscmsitkol
 
What’s my job again? Slides from Mark Simos talk at 2025 Tampa BSides
Mark Simos
 
“Squinting Vision Pipelines: Detecting and Correcting Errors in Vision Models...
Edge AI and Vision Alliance
 
Mastering Financial Management in Direct Selling
Epixel MLM Software
 
Designing_the_Future_AI_Driven_Product_Experiences_Across_Devices.pptx
presentifyai
 
Automating Feature Enrichment and Station Creation in Natural Gas Utility Net...
Safe Software
 
“NPU IP Hardware Shaped Through Software and Use-case Analysis,” a Presentati...
Edge AI and Vision Alliance
 
Newgen Beyond Frankenstein_Build vs Buy_Digital_version.pdf
darshakparmar
 
AI Penetration Testing Essentials: A Cybersecurity Guide for 2025
defencerabbit Team
 
Transforming Utility Networks: Large-scale Data Migrations with FME
Safe Software
 
Ericsson LTE presentation SEMINAR 2010.ppt
npat3
 
Cryptography Quiz: test your knowledge of this important security concept.
Rajni Bhardwaj Grover
 

Functional Programming in C# and F#

  • 2. #dotNETSpain2015#dotNETSpain2015 Software Engineer at Green Eagle Solutions .Net and Web developer Collaborator of FunScript project Organizer of Madrid .Net and F# Meetups About me
  • 3. #dotNETSpain2015#dotNETSpain2015 Personal view of functional programming Every language and every programmer understands functional programming a bit differently. There will also be some simplifications. Bias towards F# but I also love C# The sentence that will repeat most in this talk: “possible in C#, idiomatic in F#” Not an utilitarian-only approach Like: “Immutability is good because makes parallelism easier” ...but won't bore you with tough Maths If only because I wouldn't be able to. Disclaimer
  • 4. #dotNETSpain2015#dotNETSpain2015 Juan Pedro Villa Isaza, Category Theory applied to Functional Programming […] we are considering the objects and morphisms of Set to be the sets of all sets and all functions, respectively, which would lead to a paradox such as the set of all sets not members of themselves. For this reason, we ought to assume, for instance, that there is a big enough set, the universe, and take the objects of Set to be the sets which are members of the universe, that is, small sets. However, we shall not go into detail about mathematical foundations of category theory(*). (*) Thank goodness! Can functional really help me?
  • 5. #dotNETSpain2015#dotNETSpain2015 My boss, at the office Download real-time market price data from the internet at periodical intervals, insert it into the database and throw an event if the next hour price is lower than the threshold. In that case, communicate with the SCADA system through the OPC protocol to stop the wind turbines and check if the response has been successful. Is there really anyway the former can help me with the latter? Can functional really help me?
  • 6. #dotNETSpain2015#dotNETSpain2015 We all use Math to write performant code Yes, those algorithms you copy from StackOverflow are Math ;) Functional uses Math to organize your code Or as others like to say, to reason about your code. Two main topics... Alonzo Church's Lambda Calculus Category Theory What is functional programming?
  • 8. #dotNETSpain2015#dotNETSpain2015 Turing revisited Only three rules to express all possible computations (e stands for expression) Examples of lambdas: e ::= x Reference Func<int, int> f = x => x + x; // C# | λx.e Definition let f x = x + x // F# | e e Application let f' = fun x -> x + x // F# Wait, there is reference but no assignment? In strict functional there's no assignment, only binding. Binding is the same as definition an application at once. There's no re-binding either, and thus mutability is an alien concept. Alonzo Church's Lambda Calculus
  • 9. Binding int add5(int x) { var five = 5; // Assigning a variable in local scope return x + five; // and performing a computation with it... } int add5_(int x) { Func<int, int> f = five => x + five; // ...is the same as defining a function return f(5); // and applying it } int add5__(int x) { var five = 5; // Look again: this is the parameter return x + five; // and this is the body of the function } let add5 x = let five = 5 // Now in F# x + five // These three blocks are identical let add5' x = (fun five -> x + five)(5) // Definition and application let add5'' x = let five = 5 in // With the verbose syntax, you can see x + five // the body of the binding more easily let add5''' x = let five = 5 // Error: binding body missing (in local scope)
  • 10. #dotNETSpain2015#dotNETSpain2015 Q. Is this not a limitation to the expressiveness of the language? A. Maybe, but if you look around you'll see that this design pattern is very common in nature. Fractal theory Complex design emerge from simple patterns. Every element has very few dependencies. Same structure at all levels: expression < function < module/file < library Why few rules is a good thing?
  • 12. #dotNETSpain2015#dotNETSpain2015 Lambda Calculus uses only expressions Did you notice statements were also missing in Alonzo's rules? Statements are like void functions They don't return a value, thus they only can have an influence in your program through side-effects. Statements are everywhere Variable declaration Conditionals: if/else, switch Loops: for, do, while Exception: try/catch Scope: using Void functions: I/O, state Expressions vs Statements
  • 13. Program flow This is how the program flow looks with staments. Notice there's no return arrow. “Well, it doesn't look so bad” Really? Let's see it with side-effects.
  • 14. Program flow Side-effects break encapsulation. Diagrams cannot be accurately represented with statements. Side-effects depend on mutable state for every minor action (loops).
  • 15. Alternatives to statements Conditionals → ?: operator Switch → Pattern Matching Loops → LINQ, recursion Exceptions → Monads
  • 16. #dotNETSpain2015#dotNETSpain2015 Natural flow Fluent APIs (e.g. LINQ) use expressions to chain operations naturally. Code readability is improved (see next page: visual honesty). Branching Techniques like pattern matching allow natural branching of the code. The Abstract Syntax Tree (AST) builds naturally. Diagrams can be represented more accurately. Pure functions Strict functional only allows pure functions. Pure functions always return a value and don't have side-effects. They don't break the program flow. Expression merits
  • 17. Visual Honesty with Fluent APIs Source: www.theburningmonk.com
  • 18. Pattern Matching The feature that sacrificed itself so C# 6.0 could be released on time
  • 20. Pattern Matching // With some effort you can still get switch expressions in C# enum Pet { Dog, Cat, Bird } static class Extensions { public static T Switch<T>(this Pet pet, Func<T> dog, Func<T> cat, Func<T> bird) { switch (pet) { case Pet.Dog: return dog(); case Pet.Cat: return cat(); case Pet.Bird: return bird(); default: throw new Exception("Inexhaustive matching"); } } } class Program { public int HowOldIsMyPet(int animalYears, Pet pet) { return pet.Switch( dog: () => animalYears * DOG_YEARS, cat: () => animalYears * CAT_YEARS, bird:() => animalYears * BIRD_YEARS ); } }
  • 21. Pattern Matching // Or even Union Types (aka Sum or Algebraic Types) public abstract class Option<T> { public readonly T Value; Option() { } Option(T value) { Value = value; } public sealed class Some : Option<T> { public Some(T value) : base(value) { } } public sealed class None : Option<T> { public None() : base() { } } public TOutput Match<TOutput>(Func<T, TOutput> some, Func<TOutput> none) { return this is Some ? some(Value) : none(); } } class Program { public Option<string> foo() { return new Option<string>.Some("Foo!"); } public string bar() { return foo().Match( some: name => "FOUND: " + name, none: () => "NOTHING"); } }
  • 22. Pattern Matching // In F# these constructs are idiomatic and the syntax is much terser // Most of the times we use union types with Pattern Matching // Union types look like enum, but they can actually contain any value // We can extract this value when pattern matching type Pet = | Dog of int | Cat of int | Bird of int let howOldIsMyPet pet years = match pet with | Dog dy -> years * dy | Cat cy -> years * cy | Bird by -> years * by // Dummy methods let riskyFn(): int option = failwith "Not implemented" let doSth(i: int): unit = failwith "Not implemented" // Option type is a particular union type and it's built-in let main() = match riskyFn() with | Some i -> doSth i | None -> ()
  • 23. Syntax Trees are also in Nature
  • 26. #dotNETSpain2015#dotNETSpain2015 You're already using monads LINQ and Task are also monads. Sort of. If I already use them, do I need the theory? Think of it as the garbage collector, when you try to learn a bit about it, you can use it more efficiently. But, what is category anyway? Is it not the same as a set? Good news! (maybe)
  • 27. #dotNETSpain2015#dotNETSpain2015 A collection with three components A collection of objects A collection of morphisms Composition of the morphisms, which must be associative How do they map to C#/F#? Objects are types (Attention!) Morphisms are functions In F#, composition is the >> operator (f >> g)(x) = f(g(x)) In C#, composition is often represented with fluent APIs Task.Run(() => foo()) .ContinueWith(x => bar(x)) What is a category?
  • 28. #dotNETSpain2015#dotNETSpain2015 CT provides us with a formal language If the program needs to be deterministic, we need a deterministic way to think about it. Obeying the laws it dictates can give us a proof of correctness. More practically, we can generate random tests to check whether the expected properties of our types are being fulfilled (FSCheck). CT teaches us about transformations If our types and functions (categories) follow certain laws, we know we can apply some specific transformations. This is great, because there are many categories following these rules which we are not usually aware of. We are going to consider these categories as contexts as in non- deterministic, sequential or asynchronous contexts. What is Category Theory useful for?
  • 29. #dotNETSpain2015#dotNETSpain2015 Functors map one category into another It could be represented as an interface like this (pseudo code): F<a> Map<F,a,b>(this F<a> input, Func<a,b> f) // C# map: ('a → 'b) → 'F<'a> → 'F<'b> // F# The Functor must follow these rules: F(id a) = id(F a) // identity F(f >> g) = F(f) >> F(g) // composition Attention! The language doesn't enforce these rules, we must check them ourselves... but this is usually a work for library writers :) The .NET type system doesn't allow this signature. However many contexts (say, generic types) implement it. Do you recognize it? Our first transformation: the Functor
  • 30. Functors in C# and F# public static Task<TOutput> Select<T, TOutput>(this Task<T> input, Func<T, TOutput> f) { return input.ContinueWith(t => f(t.Result)); } public static Nullable<TOutput> Select<T, TOutput>(this Nullable<T> input, Func<T, TOutput> f) where TOutput : struct { return input.HasValue ? new Nullable<TOutput>(f(input.Value)) : new Nullable<TOutput>(); } myList.Select(x => x + x); // Sequential context myTask.Select(x => x + x); // Asynchronous context myNullable.Select(x => x + x); // Non-deterministic context // In F#, most contexts implement the map function // Instead of extension methods we often use module-bound functions type Async<'a> with static member map f x = async { let! y = x in return f y } let myList = [1; 2; 3;] let myOption: Option<int> = None // Option is preferred over Nullable let myAsync: Async<int> = async { return 1 } // Async is prererred over Task List.map (fun x -> x + x) myList // Functions can be chained with |> or >> Option.map (fun x -> x + x) myOption // myList |> List.map f |> List.map f' Async.map (fun x -> x + x) myAsync // List.map (f >> g) myList
  • 31. #dotNETSpain2015#dotNETSpain2015 Abstraction is one pillar of functional Everybody wants to program in a synchronous, deterministic context. We don't need to worry about the implementation details of translating our computation to the context, the library does it for us. This is may be trivial in certain contexts (IEnumerable, Nullable) but not in others (concurrent and parallel programming). The garbage collector for example has been abstracting the context of heap memory for years. Abstraction favors composability We can apply the same functions to different context or, at least, the same programming style. Why abstract the context?
  • 32. #dotNETSpain2015#dotNETSpain2015 What if we want to combine several contexts? With map we can only apply a computation to a specific context. Sometimes we need to apply a function to several contexts at once. For example if we need to check all nullable fields of a UI form. Then we need to move one step further and see Applicative Functors. But before that we need to tackle another topic... Partial applications When mapping is not enough
  • 33. #dotNETSpain2015#dotNETSpain2015 Pure functions only take one argument For example, when we see a function like this in F#: let f x y = x + y (We can also pass tuples, but let's focus on partial application no.) It would translate to C# like: Func<int, Func<int, int>> f = x => y => x + y; This way, if we apply only one argument we get a partially applied function: var add5 = f(5); // add5 == x => x + 5; Why would we need that? Composability, remember? Anyway, with this knowledge we can keep on. Partial applications
  • 34. Applicative Functors in C# // First lift the curried function to the domain of the context public static IEnumerable<a> Pure<a>(a input) { return new a[] { input }; } // Then apply the function to the first operand. As the result is a partially applied // function, we can still apply it to the rest of the operands public static IEnumerable<b> Apply<a, b>(IEnumerable<Func<a, b>> liftedFn, IEnumerable<a> input) { foreach (var f in liftedFn) foreach (var x in input) yield return f(x); } // Test Func<int, Func<int, int>> add = x => y => x + y; var lifted1 = Pure(add); var lifted2 = Apply(lifted1, new int[] { 1, 2 } ); Apply(lifted2, new int[] { 3, 4 }); // Output: 4, 5, 5, 6
  • 35. Applicative Functors in C# public static partial class Option { public static Option<a> Pure<a>(a input) { return new Option<a>.Some(input); } public static Option<b> Apply<a, b>(Option<Func<a, b>> liftedFn, Option<a> input) { return liftedFn.Match( some: f => Option.Map(input, f), none: () => new Option<b>.None() ); } } public static partial class Async { public static Task<a> Pure<a>(a input) { return Task.Run(() => input); } /// <summary>Caution: Simplified code, no error nor cancellation checks</summary> public static Task<b> Apply<a, b>(Task<Func<a, b>> liftedFn, Task<a> input) { var tcs = new TaskCompletionSource<b>(); liftedFn.ContinueWith(f => input.ContinueWith(x => tcs.SetResult(f.Result(x.Result)) )); return tcs.Task; } }
  • 36. Applicative Functors in C# // Downloading several web pages using the Applicative Functor var downloader = new WebPageDownloader(); Func<string, Task<string>> fetch10 = url => downloader.FetchLinesAsync(url, 10); Func<string, Func<string, Func<string, string>>> curry = x => y => z => x + y + z; var res1 = await Async.Apply( Async.Apply( Async.Apply( Async.Pure(curry), fetch10("http://microsoft.github.io")), fetch10("http://fsharp.org")), fetch10("http://funscript.info") ); // Obviously, the syntax is not very pretty. // We can simplify it by providing methods to lift // functions with a fixed number of arguments. // Like...
  • 37. Applicative Functors in C# public static partial class Async { // We can take the chance to add some optimizations (like parallelism) // But let's keep it simple for now public static Task<e> Lift3<a, b, c, e>(Func<a, b, c, e> f, Task<a> x, Task<b> y, Task<c> z){ Func<a, Func<b, Func<c, e>>> curry = _x => _y => _z => f(_x, _y, _z); var lifted1 = Pure(curry); var lifted2 = Apply(lifted1, x); var lifted3 = Apply(lifted2, y); return Apply(lifted3, z); } } // Now the previous code can be rewritten as: await Async.Lift3( (x,y,z) => x+y+z, fetch10("http://microsoft.github.io"), fetch10("http://fsharp.org"), fetch10("http://funscript.info") );
  • 39. Applicative Functors in F# // In F#, thanks to type inference and other features the syntax is much terser // Also, many of the functions we need are already implemented // We can define our custom operators for an even lighter syntax too module Seq = let ``pure`` f = seq { yield f } // pure is a keyword in F# let (<*>) f a = // <*> is often used for applying seq { for f in f do for a in a do yield f a } let (<!>) f a = ``pure`` f <*> a // Convenience operator let f x y = x + y // Quick tests printfn "%A" (f <!> [3;4] <*> [2;1]) printfn "%A" (f <!> [3;4] <*> []) module Option = let (<*>) f a = match f with | Some f -> Option.map f a | None -> None let ``pure`` f = Some f let (<!>) f a = ``pure`` f <*> a printfn "%A" ((+) <!> Some 5 <*> Some 4) // Quick tests printfn "%A" ((+) <!> Some 5 <*> None )
  • 40. Applicative Functors in F# module Async = let ``pure`` f = async { return f } let (<*>) f a = async { let! f = f let! a = a return f a } let (<!>) f a = ``pure`` f <*> a // Downloading content from the internet let fetchLines (url: string) i = async { let rec append i (s: StreamReader) (b: StringBuilder) = match i with | 0 -> b.ToString() | _ -> s.ReadLine() |> b.AppendLine |> append (i-1) s let req = WebRequest.Create(url) use! resp = req.AsyncGetResponse() use stream = resp.GetResponseStream() use reader = new StreamReader(stream) return append i reader (StringBuilder()) } (fun x y z -> String.length x + String.length y + String.length z) <!> fetchLines "http://microsoft.github.io" 10 <*> fetchLines "http://fsharp.org" 10 <*> fetchLines "http://funscript.info" 10 |> Async.RunSynchronously |> printfn "Chars fetched: %i"
  • 41. #dotNETSpain2015#dotNETSpain2015 What's a monad anyway? A monad is a monoid in the category of endofunctors, what's the problem? http://james-iry.blogspot.com.es/2009/05/brief-incomplete-and-mostly- wrong.html What's a monad useful for? We've just seen how to lift a function so it can be applied to operands “wrapped” in a context. However, there are many cases when we want to unwrap an operand and return a result already in the context. Think of: Sequential → Extract an element from a collection and return a collection (LINQ SelectMany()) Non-deterministic → Extract the value of Nullable, Option, Either and return the result of a risky operation Async → Extract the result of an asynchronous operation and perform another asynchronous operation Monad is coming
  • 42. #dotNETSpain2015#dotNETSpain2015 So we need a transformation with the following signature: M<a> Return<a>(a input) // Same as Pure in Applicatives M<b> Bind<a,b>(M<a> input, Func<a,M<b>> f) return: 'a → 'M<'a> bind: 'a → ('M<'a> → 'M<'b>) → 'M<'b> The return function is used to “leave the monad.” As monadic expressions are just abstract computations that we need later to apply into a context, the return value must be wrapped in the context. Thus, we have to “wrap” the result before leaving the monad. (Depending on how the language implements the concept of monad, we may need to implement other functions. But let's ignore them for now.) Mapping vs Binding
  • 43. Monads in C# public static partial class Seq { public static IEnumerable<a> Return<a>(a input) { return Pure(input); } public static IEnumerable<b> Bind<a, b>(IEnumerable<a> input, Func<a, IEnumerable<b>> f) { return input.SelectMany<a, b>(f); } } public static partial class Option { public static Option<a> Return<a>(a input) { return Pure(input); } public static Option<b> Bind<a, b>(Option<a> input, Func<a, Option<b>> f) { return input.Match( some: v => f(v), none: () => new Option<b>.None() ); } } public static partial class Async { public static Task<a> Return<a>(a input) { return Pure(input); } /// <summary>Caution: Simplified code, no error nor cancellation checks</summary> public static Task<b> Bind<a, b>(Task<a> input, Func<a, Task<b>> f) { var tcs = new TaskCompletionSource<b>(); input.ContinueWith(x => f(x.Result).ContinueWith(y => tcs.SetResult(y.Result))); return tcs.Task; }
  • 44. Monads in F# module Seq = let ``return`` f = seq { yield f } let (>>=) xs f = // This is the usual operator for bind seq { for x in xs do yield! f x } module Option = let ``return`` f = Some f // Already implemented in FShap.Core let (>>=) a f = match a with | Some a -> f a | None -> None module Async = // Already implemented in FShap.Core let ``return`` = async.Return let (>>=) a f = async.Bind(a, f)
  • 45. And this is how we use them var downloader = new WebPageDownloader(); // C# Func<string, Task<string>> fetch10 = url => downloader.FetchLinesAsync(url, 10); var res1 = await Async.Bind( fetch10("http://microsoft.github.io"), x => Async.Bind( fetch10("http://fsharp.org"), y => Async.Bind( fetch10("http://funscript.info"), z => Async.Return(x + y + z) ) ) ); let fetchLines (url: string) i = async { // F# let rec append i (s: StreamReader) (b: StringBuilder) = match i with | 0 -> b.ToString() | _ -> s.ReadLine() |> b.AppendLine |> append (i-1) s let req = WebRequest.Create(url) use! resp = req.AsyncGetResponse() use stream = resp.GetResponseStream() use reader = new StreamReader(stream) return append i reader (StringBuilder())} async.Bind(fetchLines "http://microsoft.github.io" 10, fun x -> async.Bind(fetchLines "http://fsharp.org" 10, fun y -> async.Bind(fetchLines "http://funscript.info" 10, fun z -> async.Return(x + y + z)))) |> Async.RunSynchronously
  • 46. #dotNETSpain2015#dotNETSpain2015 Is this any advance at all? Monads can be really useful, but nesting function is not pretty and soon leads to “callback hell.” That's why most languages implementing monads add a macro system (sugar syntax) in order to make them more pleasant. In C# we can use extension methods or even abuse the LINQ special syntax. In F# we have computation expressions, designed for monads but including also many extra features: Generators seq { for x in xs do yield x + x } Query expressions query { from x in db do select x } Macros for .NET constructs use! But this is horrible!
  • 47. Monads revisited // Extension method to use LINQ syntax with Task public static Task<b> Select<a, b>(this Task<a> input, Func<a, b> f) { return Async.Map(input, f); } public static Task<c> SelectMany<a,b,c>( this Task<a> input, Func<a, Task<b>> f, Func<a, b, c> projection) { return Bind(input, outer => Bind(f(outer), inner => Return(projection(outer, inner)))); } // Now we can concatenate async operations using LINQ syntax await (from x in fetch10("http://microsoft.github.io") from y in fetch10("http://fsharp.org") let url = "http://funscript.info" from z in fetch10(url) select x + y + z); // In F# the boiler plate code has already been done for us in Async // But we can implement our own custom computation expressions easily async { let! x = fetchLines "http://microsoft.github.io" 10 let! y = fetchLines "http://fsharp.org" 10 let url = "http://funscript.info" let! z = fetchLines url 10 return x + y + z } |> Async.RunSynchronously
  • 48. #dotNETSpain2015#dotNETSpain2015 Why monads seems to be some pervasive in functional programming? Why I don't hear to talk about functors or applicatives so much? Monads are an elegant idea. Same as map/reduce they can be used to deal in a similar fashion with many different problems. In strict functional programming they have been used to tackle side- effects, for example: IO, State monads We can also use the F# Async monad to code state machines without flags. Feel the monad! OK, I get the idea but...
  • 49. State machines without state? The state is in the program flow
  • 50. #dotNETSpain2015 Now you're ready to join the functional army!
  • 52. #dotNETSpain2015#dotNETSpain2015 http://ericlippert.com/2013/02/21/monads-part-one/ Monads and C#, by Eric Lippert Real-World Functional Programming, with examples in F# and C# By Tomas Petricek and Jon Skeet http://fsharpforfunandprofit.com/ By Scott Wlaschin The site to learn F# and functional programming, from an F# perspective http://learnyouahaskell.com/ By Miran Lipovaca A strict functional language helps you understand better the concepts http://bugsquash.blogspot.com.es/ By Mauricio Scheffer References