Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
F# for C# programmers
@ScottWlaschin
fsharpforfunandprofit.com
A language that doesn't affect the way you
think about programming, is not worth
knowing – Alan Perlis
“F# is slightly better than C#,
but not so much that it's
really worth the effort to
move towards it.”
“Learning F# was on...
About F#
• Developed by Microsoft Research
– Shipped withVisual Studio in 2010
• Open source
– On github
• Cross platform
...
A tour of F#
• Differences between C# and F#
– Concise syntax
– Type inference
– Different defaults
– Different philosophy...
SYNTAX
public class Person
{
public Person(string name, DateTime birthday)
{
_name = name;
_birthday = birthday;
}
private readon...
Syntax difference:
Indentation instead
of curly braces
public class Person
{
public Person(string name, DateTime birthday)
{
_name = name;
_birthday = birthday;
}
private readon...
public class Person
{
public Person(string name, DateTime birthday)
{
_name = name;
_birthday = birthday;
}
private readon...
public class Person =
public Person(string name, DateTime birthday) =
_name = name;
_birthday = birthday;
private readonly...
public class Person =
public Person(string name, DateTime birthday) =
_name = name;
_birthday = birthday;
private readonly...
public class Person =
public Person(string name, DateTime birthday) =
_name = name;
_birthday = birthday;
private readonly...
People who
complain about
using a language
with syntactic
whitespace
People who
have spent time
using a language
with synt...
Syntax difference:
Automatically create
backing fields from
constructor parameters
public class Person =
public Person(string name, DateTime birthday) =
_name = name;
_birthday = birthday;
private readonly...
public class Person =
public Person(string name, DateTime birthday) =
...
public string Name =
get { return name; }
public...
Syntax difference:
Merge the primary constructor
with the class definition
public class Person =
public Person(string name, DateTime birthday) =
...
public string Name =
get { return name; }
public...
public class Person(string name, DateTime birthday) =
public string Name =
get { return name; }
public DateTime Birthday =...
Syntax difference:
Less syntax noise
public class Person(string name, DateTime birthday) =
public string Name =
get { return name; }
public DateTime Birthday =...
public class Person(string name, DateTime birthday) =
public string Name =
return name;
public DateTime Birthday =
return ...
public class Person(string name, DateTime birthday) =
public string Name =
return name;
public DateTime Birthday =
return ...
public class Person(string name, DateTime birthday) =
public string Name =
return name
public DateTime Birthday =
return b...
Syntax difference:
No “return” needed
public class Person(string name, DateTime birthday) =
public string Name =
return name
public DateTime Birthday =
return b...
public class Person(string name, DateTime birthday) =
public string Name =
name
public DateTime Birthday =
birthday
F# is ...
Difference:
Members are public by default
public class Person(string name, DateTime birthday) =
public string Name =
name
public DateTime Birthday =
birthday
class Person(string name, DateTime birthday) =
string Name =
name
DateTime Birthday =
birthday
Difference:
Type inference!
class Person(string name, DateTime birthday) =
string Name =
name
DateTime Birthday =
birthday
Why do we have to
repeat th...
class Person(string name, DateTime birthday) =
Name =
name
Birthday =
birthday
class Person(string name, DateTime birthday) =
member this.Name =
name
member this.Birthday =
birthday
class Person(string name, DateTime birthday) =
member this.Name =
name
member this.Birthday =
birthday
member this.Age() =...
Syntax difference:
Type annotations
class Person(string name, DateTime birthday) =
member this.Name =
name
member this.Birthday =
birthday
member this.Age() =...
class Person(name: string, birthday: DateTime ) =
member this.Name =
name
member this.Birthday =
birthday
member this.Age(...
Syntax difference:
Different keywords
class Person(name: string, birthday: DateTime ) =
member this.Name =
name
member this.Birthday =
birthday
member this.Age(...
type Person(name: string, birthday: DateTime ) =
member this.Name =
name
member this.Birthday =
birthday
member this.Age()...
Compared with modern C#
class Person(string name, DateTime birthday)
{
public string Name { get; } = name;
public DateTime Birthday { get; } = bir...
Functional programming syntax
type Person = {
Name: string
Birthday: DateTime
}
let age person =
let daysDiff = DateTime.Today.Subtract(person.Birthday)...
// age : Person -> int
type Person = {
Name: string
Birthday: DateTime
}
let age person =
let daysDiff = DateTime.Today.Su...
Syntax is never the most important
thing about a programming language.
But…
Observation:
21 lines of code has shrunk
to 5 lines of code
You see 3x more
code on your
screen!
public class Person
{
public Person(string name, DateTime birthday)
{
_name = name;
_birthday = birthday;
}
private readon...
TYPE INFERENCE
Type inference
let doSomething f x =
let y = f (x + 1)
"hello" + y
Type inference
let doSomething f x =
let y = f (x + 1)
"hello" + y
Type inference
let doSomething f x =
let y = f (x + 1)
"hello" + y
Inferred type of doSomething :
f:(int -> string) -> x:i...
Type inference
// C# code
public IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>(
IEnumerable<TSource> source...
DIFFERENT DEFAULTS
F# has different defaults
• Immutable by default
– mutable is special case
• Non-null types/classes by default
– Nullable ...
Immutability by default
Mutability
let x = 1
x <- 2 // assign new value
Mutability
let mutable x = 1
x <- 2 // assign new value
Not nullable by default
Non null
type Person = {
Name: string
Birthday: DateTime
}
let x : Person = null
Non null
[<AllowNullLiteralAttribute>]
type Person(name: string, birthday: DateTime) =
member this.Name = name
member this...
Structural equality by default
(for record types)
Structural equality
type Person = {
Name: string
Birthday: DateTime
}
let bday = DateTime(1980,1,1)
let alice1 = {Name="Al...
Everything must be initialized
Initialization
type Person = {
Name: string
Birthday: DateTime
}
let alice : Person
Initialization
type Person = {
Name: string
Birthday: DateTime
}
let alice = {Name="Alice"}
DIFFERENT PHILOSOPHY
Different philosophies
• C# historically comes from C-like approach.
• F# comes from ML, a MetaLanguage for
proving things.
Goal: Predictable code
• Can you understand the code using only the
information that you have right in front of you?
• You...
Example 1
The answer is
"hello world".
What value is y?
var x = 1;
DoSomething(x);
var y = "hello " + x;
Example 1
function DoSomething (foo) { x = "world"; }
var x = 1;
DoSomething(x);
var y = "hello " + x;
Predictable code
C# is more predictable than JavaScript!
In C#, if you don't match up the types properly,
you get a compil...
How to make your language predictable:
• Variables should not be allowed to change their type
Example 2
// create two customers
var cust1 = new Customer(99, "J Smith");
var cust2 = new Customer(99, "J Smith");
// tru...
How to make your language predictable:
• Variables should not be allowed to change their type
• Objects with the same valu...
Example 3
// create a customer and an order
var cust = new Customer(99, "J Smith");
var order = new Order(99, "J Smith");
...
How to make your language predictable:
• Variables should not be allowed to change their type
• Objects with the same valu...
Example 4
// create a customer
var cust = new Customer();
// what is the expected output?
Console.WriteLine(cust.Address.C...
How to make your language predictable:
• Variables should not be allowed to change their type
• Objects with the same valu...
Example 5
// create a customer
var cust = new Customer(99, "J Smith");
// add it to a set
var processedCustomers = new Has...
Example 5
// create a customer
var cust = new ImmutableCustomer(99, "J Smith");
// add it to a set
var processedCustomers ...
How to make your language predictable:
• Variables should not be allowed to change their type
• Objects with the same valu...
Example 6
// create a repository
var repo = new CustomerRepository();
// find a customer by id
var customer = repo.GetById...
Example 6
// create a repository
var repo = new CustomerRepository();
// find a customer by id
var customerOrError = repo....
How to make your language predictable:
• Variables should not be allowed to change their type
• Objects with the same valu...
F# aims to be a predictable language:
• Variables are not be allowed to change their type
• Objects with the same values a...
FUNCTIONAL FIRST
Core principles of functional programming
Function
Parameterize all the things
Functions
Composition everywhere
FP Principle:
Functions are things
Function
Functions as things
The Tunnel of
Transformation
Function
apple -> banana
A function is a thing which
transforms inputs to...
Functions as things
let x = 1
let add x y = x + y
A function is a standalone thing,
not attached to a class
It can be used for inputs and outputs
of other functions
input
A function can be an output
A function is a standalone thing,
not attached to a class
It can be used for inputs and ...
output
input
A function can be an output
A function can be an input
A function is a standalone thing,
not attached to a cl...
output
input
input output
A function can be an output
A function can be an input
A function can be a parameter
A function ...
output
input
input output
A function can be an output
A function can be an input
A function can be a parameter
A function ...
FP principle:
Composition everywhere
Function composition
Function 1
apple -> banana
Function 2
banana -> cherry
Function composition
>>
Function 1
apple -> banana
Function 2
banana -> cherry
Function composition
New Function
apple -> cherry
Can't tell it was built from
smaller functions!
Where did the banana go?...
add1 double5 12
let add1 x = x + 1
let double x = x + x
let add1_double =
add1 >> double
let x = add1_double 5
Composition...
add1 double square5 144
let add1_double_square =
add1 >> double >> square
let x = add1_double_square 5
Composition (F#)
Func<int, int> add1 = x => x + 1;
Func<int, int> doubl = x => x + x;
Func<int, int> square = x => x * x;
var composed =
ad...
Piping (F#)
add1 5 // = 6
double (add1 5) // = 12
square (double (add1 5)) // = 144
5 |> add1 // = 6
5 |> add1 |> double // = 12
5 |> ...
Piping (C#)
5.Pipe(Add1); // = 6
5.Pipe(Add1).Pipe(Double); // = 12
5.Pipe(Add1).Pipe(Double).Pipe(Square);
Func<int, int> add1 = x =>...
Why we say F# is "functional-first"
• F# makes FP easy
• C# makes FP possible
– but it's awkward and not idiomatic
FP Guideline:
Parameterize all the things
Parameterize all the things
let printList() =
for i in [1..10] do
printfn "the number is %i" i
Parameterize all the things
let printList aList =
for i in aList do
printfn "the number is %i" i
Parameterize all the things
let printList anAction aList =
for i in aList do
anAction i
FPers would parameterize the actio...
Parameterize all the things
public static int Product(int n)
{
int product = 1;
for (int i = 1; i <= n; i++)
{
product *= ...
public static int Product(int n)
{
int product = 1;
for (int i = 1; i <= n; i++)
{
product *= i;
}
return product;
}
publi...
Parameterize all the things
let fold action initialValue list =
let mutable totalSoFar = initialValue
for item in list do
...
Parameterize all the things
let fold action initialValue list =
let mutable totalSoFar = initialValue
for item in list do
...
Parameterize all the things
let product n =
let initialValue = 1
let action productSoFar x = productSoFar * x
[1..n] |> Li...
Big topic! Not enough time right now !
More at fsharpforfunandprofit.com/fppatterns
ALGEBRAIC TYPE SYSTEM
What are F# types?
A type is not a class
What is a type?
A type is a just a name
for a set of things
Set of
valid inputs
Set of
valid outputs
Function
Set of
valid inputs
Set of
valid outputs
Function
1
2
3
4
5
6
This is type
"integer"
A type is a just a name
for a set of ...
Set of
valid inputs
Set of
valid outputs
Function
This is type
"string"
"abc"
"but"
"cobol"
"double"
"end"
"float"
A type ...
Set of
valid inputs
Set of
valid outputs
Function
This is type
"Person"
Donna Roy
Javier Mendoza
Nathan Logan
Shawna Ingra...
Set of
valid inputs
Set of
valid outputs
Function
This is type
"Fruit"
A type is a just a name
for a set of things
Set of
valid inputs
Set of
valid outputs
Function
This is a type
containing functions
A type is a just a name
for a set of...
F# types can be composed
"Algebraic type system"
New types are built from smaller types using:
“AND”
“OR”
Example: pairs, tuples, records
FruitSalad = One each of and and
“AND” types
type FruitSalad = {
Apple: AppleVariety
Banan...
Snack = or or
“OR” types
type Snack =
| Apple of AppleVariety
| Banana of BananaVariety
| Cherry of CherryVariety
Real world example
of type composition
Example of some requirements:
We accept three forms of payment:
Cash, Check, or Card.
For Cash we don't need any extra inf...
interface IPaymentMethod
{..}
class Cash() : IPaymentMethod
{..}
class Check(int checkNo): IPaymentMethod
{..}
class Card(...
type CheckNumber = int
type CardNumber = string
In F# you would probably implement by composing
types, like this
type CheckNumber = int
type CardNumber = string
type CardType = Visa | Mastercard
type CreditCardInfo = CardType * CardNum...
type CheckNumber = int
type CardNumber = string
type CardType = Visa | Mastercard
type CreditCardInfo = CardType * CardNum...
type CheckNumber = int
type CardNumber = string
type CardType = Visa | Mastercard
type CreditCardInfo = CardType * CardNum...
type CheckNumber = int
type CardNumber = string
type CardType = Visa | Mastercard
type CreditCardInfo = CardType * CardNum...
F# design principle:
Types are executable documentation
type Deal = Deck –› (Deck * Card)
type PickupCard = (Hand * Card) –› Hand
Types are executable documentation
type Suit = C...
Types are executable documentation
type CardType =Visa | Mastercard
type CardNumber = CardNumber of string
type CheckNumbe...
Another big topic and not enough time  
More on DDD and designing with types at
fsharpforfunandprofit.com/ddd
INTERACTIVITY
Interactivity demo
Slides and video here
F# consulting
fsharpforfunandprofit.com/csharp
F# for C# programmers
F# for C# Programmers
Upcoming SlideShare
Loading in …5
×

F# for C# Programmers

4,303 views

Published on

(Video and more at fsharpforfunandprofit.com/csharp)

Curious about F# and want to understand how is it different from C#?

In this talk, we'll look at the basics of coding in F#, and how functional programming differs from object-oriented programming. Along the way, there will be many examples showing the same code written in C# and F# so that you can see for yourself how the two languages differ in style and approach.

Published in: Software

F# for C# Programmers

  1. 1. F# for C# programmers @ScottWlaschin fsharpforfunandprofit.com
  2. 2. A language that doesn't affect the way you think about programming, is not worth knowing – Alan Perlis
  3. 3. “F# is slightly better than C#, but not so much that it's really worth the effort to move towards it.” “Learning F# was one of the biggest boosts in my career as a C# developer. I don't use it professionally (I wish I could) but this knowledge made me a better programmer.”
  4. 4. About F# • Developed by Microsoft Research – Shipped withVisual Studio in 2010 • Open source – On github • Cross platform – Works withVS Code (and other editors) • Very active and friendly community. – Start with fsharp.org – F# Slack channel – #fsharp onTwitter
  5. 5. A tour of F# • Differences between C# and F# – Concise syntax – Type inference – Different defaults – Different philosophy • Special to F# – Functional-first – Algebraic type system – Interactivity From least to most important!
  6. 6. SYNTAX
  7. 7. public class Person { public Person(string name, DateTime birthday) { _name = name; _birthday = birthday; } private readonly string _name; private readonly DateTime _birthday; public string Name { get { return _name; } } public DateTime Birthday { get { return _birthday; } } }
  8. 8. Syntax difference: Indentation instead of curly braces
  9. 9. public class Person { public Person(string name, DateTime birthday) { _name = name; _birthday = birthday; } private readonly string _name; private readonly DateTime _birthday; public string Name { get { return _name; } } public DateTime Birthday { get { return _birthday; } } } Do we really need the braces? The indentation already gives us all the clues we need.
  10. 10. public class Person { public Person(string name, DateTime birthday) { _name = name; _birthday = birthday; } private readonly string _name; private readonly DateTime _birthday; public string Name { get { return _name; } } public DateTime Birthday { get { return _birthday; } } } Example where braces indicate blocks
  11. 11. public class Person = public Person(string name, DateTime birthday) = _name = name; _birthday = birthday; private readonly string _name; private readonly DateTime _birthday; public string Name = get { return _name; } public DateTime Birthday = get { return _birthday; } Example where indentation indicates blocks Is it really that much harder to read?
  12. 12. public class Person = public Person(string name, DateTime birthday) = _name = name; _birthday = birthday; private readonly string _name; private readonly DateTime _birthday; public string Name = get { return _name; } public DateTime Birthday = get { return _birthday; } Use '=' to start blocks
  13. 13. public class Person = public Person(string name, DateTime birthday) = _name = name; _birthday = birthday; private readonly string _name; private readonly DateTime _birthday; public string Name = get { return _name; } public DateTime Birthday = get { return _birthday; } Shift up to use less vertical space
  14. 14. People who complain about using a language with syntactic whitespace People who have spent time using a language with syntactic whitespace "Oddly enough, Python's use of whitespace stopped feeling unnatural after about twenty minutes. I just indented code, pretty much as I would have done in a C program anyway, and it worked." - Eric Raymond HelpfulVenn Diagram Overlap
  15. 15. Syntax difference: Automatically create backing fields from constructor parameters
  16. 16. public class Person = public Person(string name, DateTime birthday) = _name = name; _birthday = birthday; private readonly string _name; private readonly DateTime _birthday; public string Name = get { return _name; } public DateTime Birthday = get { return _birthday; } A lot of duplication...
  17. 17. public class Person = public Person(string name, DateTime birthday) = ... public string Name = get { return name; } public DateTime Birthday = get { return birthday; } Use the constructor params directly
  18. 18. Syntax difference: Merge the primary constructor with the class definition
  19. 19. public class Person = public Person(string name, DateTime birthday) = ... public string Name = get { return name; } public DateTime Birthday = get { return birthday; } How often do you have more than one constructor?
  20. 20. public class Person(string name, DateTime birthday) = public string Name = get { return name; } public DateTime Birthday = get { return birthday; }
  21. 21. Syntax difference: Less syntax noise
  22. 22. public class Person(string name, DateTime birthday) = public string Name = get { return name; } public DateTime Birthday = get { return birthday; } So why use ‘get’? The class is immutable. Every property is "get" only.
  23. 23. public class Person(string name, DateTime birthday) = public string Name = return name; public DateTime Birthday = return birthday; 'get' is gone!
  24. 24. public class Person(string name, DateTime birthday) = public string Name = return name; public DateTime Birthday = return birthday; Who even likes typing semicolons anyway?
  25. 25. public class Person(string name, DateTime birthday) = public string Name = return name public DateTime Birthday = return birthday Semicolons gone!
  26. 26. Syntax difference: No “return” needed
  27. 27. public class Person(string name, DateTime birthday) = public string Name = return name public DateTime Birthday = return birthday
  28. 28. public class Person(string name, DateTime birthday) = public string Name = name public DateTime Birthday = birthday F# is an expression- oriented language
  29. 29. Difference: Members are public by default
  30. 30. public class Person(string name, DateTime birthday) = public string Name = name public DateTime Birthday = birthday
  31. 31. class Person(string name, DateTime birthday) = string Name = name DateTime Birthday = birthday
  32. 32. Difference: Type inference!
  33. 33. class Person(string name, DateTime birthday) = string Name = name DateTime Birthday = birthday Why do we have to repeat the type? Can't the compiler figure it out for us?
  34. 34. class Person(string name, DateTime birthday) = Name = name Birthday = birthday
  35. 35. class Person(string name, DateTime birthday) = member this.Name = name member this.Birthday = birthday
  36. 36. class Person(string name, DateTime birthday) = member this.Name = name member this.Birthday = birthday member this.Age() = var daysDiff = DateTime.Today.Subtract(birthday).Days daysDiff / 365
  37. 37. Syntax difference: Type annotations
  38. 38. class Person(string name, DateTime birthday) = member this.Name = name member this.Birthday = birthday member this.Age() = var daysDiff = DateTime.Today.Subtract(birthday).Days daysDiff / 365
  39. 39. class Person(name: string, birthday: DateTime ) = member this.Name = name member this.Birthday = birthday member this.Age() = var daysDiff = DateTime.Today.Subtract(birthday).Days daysDiff / 365
  40. 40. Syntax difference: Different keywords
  41. 41. class Person(name: string, birthday: DateTime ) = member this.Name = name member this.Birthday = birthday member this.Age() = var daysDiff = DateTime.Today.Subtract(birthday).Days daysDiff / 365
  42. 42. type Person(name: string, birthday: DateTime ) = member this.Name = name member this.Birthday = birthday member this.Age() = let daysDiff = DateTime.Today.Subtract(birthday).Days daysDiff / 365
  43. 43. Compared with modern C#
  44. 44. class Person(string name, DateTime birthday) { public string Name { get; } = name; public DateTime Birthday { get; } = birthday; public int Age() => DateTime.Today.Subtract(birthday).Days / 365; } Modern C# equivalent with auto-properties and expression-bodied members
  45. 45. Functional programming syntax
  46. 46. type Person = { Name: string Birthday: DateTime } let age person = let daysDiff = DateTime.Today.Subtract(person.Birthday).Days daysDiff / 365
  47. 47. // age : Person -> int type Person = { Name: string Birthday: DateTime } let age person = let daysDiff = DateTime.Today.Subtract(person.Birthday).Days daysDiff / 365
  48. 48. Syntax is never the most important thing about a programming language. But…
  49. 49. Observation: 21 lines of code has shrunk to 5 lines of code
  50. 50. You see 3x more code on your screen!
  51. 51. public class Person { public Person(string name, DateTime birthday) { _name = name; _birthday = birthday; } private readonly string _name; private readonly DateTime _birthday; /// <summary> /// Full name /// </summary> public string Name { get { return _name; } } /// <summary> /// Birthday /// </summary> public DateTime Birthday { get { return _birthday; } } } public class Person(string name, DateTime birthday) = /// Full name public string Name = get { return name; } /// Birthday public DateTime Birthday = get { return birthday; } C# F# You write 1/3 as much code.
  52. 52. TYPE INFERENCE
  53. 53. Type inference let doSomething f x = let y = f (x + 1) "hello" + y
  54. 54. Type inference let doSomething f x = let y = f (x + 1) "hello" + y
  55. 55. Type inference let doSomething f x = let y = f (x + 1) "hello" + y Inferred type of doSomething : f:(int -> string) -> x:int -> string
  56. 56. Type inference // C# code public IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>( IEnumerable<TSource> source, Func<TSource, TKey> keySelector ) { ... } // F# code let GroupBy source keySelector = ... Benefits of type inference: * Less typing * Less noise, more logic Here's a more complex example
  57. 57. DIFFERENT DEFAULTS
  58. 58. F# has different defaults • Immutable by default – mutable is special case • Non-null types/classes by default – Nullable is special case • Structural equality by default – reference equality is special case • Everything must be initialized
  59. 59. Immutability by default
  60. 60. Mutability let x = 1 x <- 2 // assign new value
  61. 61. Mutability let mutable x = 1 x <- 2 // assign new value
  62. 62. Not nullable by default
  63. 63. Non null type Person = { Name: string Birthday: DateTime } let x : Person = null
  64. 64. Non null [<AllowNullLiteralAttribute>] type Person(name: string, birthday: DateTime) = member this.Name = name member this.Birthday = birthday let x : Person = null
  65. 65. Structural equality by default (for record types)
  66. 66. Structural equality type Person = { Name: string Birthday: DateTime } let bday = DateTime(1980,1,1) let alice1 = {Name="Alice"; Birthday=bday} let alice2 = {Name="Alice"; Birthday=bday} alice1 = alice2 // true or false?
  67. 67. Everything must be initialized
  68. 68. Initialization type Person = { Name: string Birthday: DateTime } let alice : Person
  69. 69. Initialization type Person = { Name: string Birthday: DateTime } let alice = {Name="Alice"}
  70. 70. DIFFERENT PHILOSOPHY
  71. 71. Different philosophies • C# historically comes from C-like approach. • F# comes from ML, a MetaLanguage for proving things.
  72. 72. Goal: Predictable code • Can you understand the code using only the information that you have right in front of you? • You’re not allowed to delve into other parts of the codebase!
  73. 73. Example 1 The answer is "hello world". What value is y? var x = 1; DoSomething(x); var y = "hello " + x;
  74. 74. Example 1 function DoSomething (foo) { x = "world"; } var x = 1; DoSomething(x); var y = "hello " + x;
  75. 75. Predictable code C# is more predictable than JavaScript! In C#, if you don't match up the types properly, you get a compile-time error not a run-time error. This is good!
  76. 76. How to make your language predictable: • Variables should not be allowed to change their type
  77. 77. Example 2 // create two customers var cust1 = new Customer(99, "J Smith"); var cust2 = new Customer(99, "J Smith"); // true or false? cust1 == cust2;
  78. 78. How to make your language predictable: • Variables should not be allowed to change their type • Objects with the same values should be equal by default.
  79. 79. Example 3 // create a customer and an order var cust = new Customer(99, "J Smith"); var order = new Order(99, "J Smith"); // true or false? cust.Equals(order);
  80. 80. How to make your language predictable: • Variables should not be allowed to change their type • Objects with the same values should be equal by default. • Comparing objects of different types is a compile- time error.
  81. 81. Example 4 // create a customer var cust = new Customer(); // what is the expected output? Console.WriteLine(cust.Address.Country)
  82. 82. How to make your language predictable: • Variables should not be allowed to change their type • Objects with the same values should be equal by default. • Comparing objects of different types is a compile-time error. • Objects must always be initialized to a valid state. Not doing so is a compile-time error.
  83. 83. Example 5 // create a customer var cust = new Customer(99, "J Smith"); // add it to a set var processedCustomers = new HashSet<Customer>(); processedCustomers.Add(cust); // process it ProcessCustomer(cust); // Is the customer still in the set? True or false? processedCustomers.Contains(cust); You can't tell! Not predictable! If ProcessCustomer mutates the customer, it might change the hash 
  84. 84. Example 5 // create a customer var cust = new ImmutableCustomer(99, "J Smith"); // add it to a set var processedCustomers = new HashSet<ImmutableCustomer>(); processedCustomers.Add(cust); // process it and return the changes var changedCustomer = ProcessCustomer(cust); // Is the customer still in the set? True or false? processedCustomers.Contains(cust); Immutability forces changed values to be returned explictly. Original value unchanged.
  85. 85. How to make your language predictable: • Variables should not be allowed to change their type • Objects with the same values should be equal by default. • Comparing objects of different types is a compile-time error. • Objects must always be initialized to a valid state. Not doing so is a compile-time error. • Once created, objects and collections must be immutable.
  86. 86. Example 6 // create a repository var repo = new CustomerRepository(); // find a customer by id var customer = repo.GetById(42); // what is the expected output? Console.WriteLine(customer.Id); What happens if the customer is missing? Is the customer null or what? You can't tell! Not predictable!
  87. 87. Example 6 // create a repository var repo = new CustomerRepository(); // find a customer by id var customerOrError = repo.GetById(42); // handle both cases if (customerOrError.IsCustomer) Console.WriteLine(customerOrError.Customer.Id); if (customerOrError.IsError) Console.WriteLine(customerOrError.ErrorMessage); Instead, build error cases into the return type.
  88. 88. How to make your language predictable: • Variables should not be allowed to change their type • Objects with the same values should be equal by default. • Comparing objects of different types is a compile-time error. • Objects must always be initialized to a valid state. Not doing so is a compile-time error. • Once created, objects and collections must be immutable. • Missing data or errors must be made explicit. No nulls allowed.
  89. 89. F# aims to be a predictable language: • Variables are not be allowed to change their type • Objects with the same values are equal by default. • Comparing objects of different types is a compile-time error. • Objects must be initialized to a valid state. Not doing so is a compile-time error.. • Once created, objects and collections are (generally) immutable. • Missing data or errors are (generally) made explicit. Nulls are a code smell.
  90. 90. FUNCTIONAL FIRST
  91. 91. Core principles of functional programming Function Parameterize all the things Functions Composition everywhere
  92. 92. FP Principle: Functions are things Function
  93. 93. Functions as things The Tunnel of Transformation Function apple -> banana A function is a thing which transforms inputs to outputs
  94. 94. Functions as things let x = 1 let add x y = x + y
  95. 95. A function is a standalone thing, not attached to a class It can be used for inputs and outputs of other functions
  96. 96. input A function can be an output A function is a standalone thing, not attached to a class It can be used for inputs and outputs of other functions
  97. 97. output input A function can be an output A function can be an input A function is a standalone thing, not attached to a class It can be used for inputs and outputs of other functions
  98. 98. output input input output A function can be an output A function can be an input A function can be a parameter A function is a standalone thing, not attached to a class It can be used for inputs and outputs of other functions
  99. 99. output input input output A function can be an output A function can be an input A function can be a parameter A function is a standalone thing, not attached to a class It can be used for inputs and outputs of other functions From this simple foundation we can build complex systems
  100. 100. FP principle: Composition everywhere
  101. 101. Function composition Function 1 apple -> banana Function 2 banana -> cherry
  102. 102. Function composition >> Function 1 apple -> banana Function 2 banana -> cherry
  103. 103. Function composition New Function apple -> cherry Can't tell it was built from smaller functions! Where did the banana go? (abstraction)
  104. 104. add1 double5 12 let add1 x = x + 1 let double x = x + x let add1_double = add1 >> double let x = add1_double 5 Composition (F#)
  105. 105. add1 double square5 144 let add1_double_square = add1 >> double >> square let x = add1_double_square 5 Composition (F#)
  106. 106. Func<int, int> add1 = x => x + 1; Func<int, int> doubl = x => x + x; Func<int, int> square = x => x * x; var composed = add1.Compose(doubl).Compose(square); composed(5); Composition (C#)
  107. 107. Piping (F#)
  108. 108. add1 5 // = 6 double (add1 5) // = 12 square (double (add1 5)) // = 144 5 |> add1 // = 6 5 |> add1 |> double // = 12 5 |> add1 |> double |> square // = 144 Standard way of nesting function calls can be confusing if too deep add1 double square5 6 12 144
  109. 109. Piping (C#)
  110. 110. 5.Pipe(Add1); // = 6 5.Pipe(Add1).Pipe(Double); // = 12 5.Pipe(Add1).Pipe(Double).Pipe(Square); Func<int, int> add1 = x => x + 1; Func<int, int> doubl = x => x + x; Func<int, int> square = x => x * x; add1 double square5 6 12 144
  111. 111. Why we say F# is "functional-first" • F# makes FP easy • C# makes FP possible – but it's awkward and not idiomatic
  112. 112. FP Guideline: Parameterize all the things
  113. 113. Parameterize all the things let printList() = for i in [1..10] do printfn "the number is %i" i
  114. 114. Parameterize all the things let printList aList = for i in aList do printfn "the number is %i" i
  115. 115. Parameterize all the things let printList anAction aList = for i in aList do anAction i FPers would parameterize the action as well: We've decoupled the behavior from the data. Any list, any action!
  116. 116. Parameterize all the things public static int Product(int n) { int product = 1; for (int i = 1; i <= n; i++) { product *= i; } return product; } public static int Sum(int n) { int sum = 0; for (int i = 1; i <= n; i++) { sum += i; } return sum; }
  117. 117. public static int Product(int n) { int product = 1; for (int i = 1; i <= n; i++) { product *= i; } return product; } public static int Sum(int n) { int sum = 0; for (int i = 1; i <= n; i++) { sum += i; } return sum; } Parameterize all the things
  118. 118. Parameterize all the things let fold action initialValue list = let mutable totalSoFar = initialValue for item in list do totalSoFar <- action totalSoFar item totalSoFar
  119. 119. Parameterize all the things let fold action initialValue list = let mutable totalSoFar = initialValue for item in list do totalSoFar <- action totalSoFar item totalSoFar
  120. 120. Parameterize all the things let product n = let initialValue = 1 let action productSoFar x = productSoFar * x [1..n] |> List.fold action initialValue let sum n = let initialValue = 0 let action sumSoFar x = sumSoFar+x [1..n] |> List.fold action initialValue Lots of collection functions like this: "fold", "map", "reduce", "collect", etc.
  121. 121. Big topic! Not enough time right now ! More at fsharpforfunandprofit.com/fppatterns
  122. 122. ALGEBRAIC TYPE SYSTEM
  123. 123. What are F# types? A type is not a class
  124. 124. What is a type? A type is a just a name for a set of things Set of valid inputs Set of valid outputs Function
  125. 125. Set of valid inputs Set of valid outputs Function 1 2 3 4 5 6 This is type "integer" A type is a just a name for a set of things
  126. 126. Set of valid inputs Set of valid outputs Function This is type "string" "abc" "but" "cobol" "double" "end" "float" A type is a just a name for a set of things
  127. 127. Set of valid inputs Set of valid outputs Function This is type "Person" Donna Roy Javier Mendoza Nathan Logan Shawna Ingram Abel Ortiz Lena Robbins GordonWood A type is a just a name for a set of things
  128. 128. Set of valid inputs Set of valid outputs Function This is type "Fruit" A type is a just a name for a set of things
  129. 129. Set of valid inputs Set of valid outputs Function This is a type containing functions A type is a just a name for a set of things
  130. 130. F# types can be composed "Algebraic type system"
  131. 131. New types are built from smaller types using: “AND” “OR”
  132. 132. Example: pairs, tuples, records FruitSalad = One each of and and “AND” types type FruitSalad = { Apple: AppleVariety Banana: BananaVariety Cherry: CherryVariety }
  133. 133. Snack = or or “OR” types type Snack = | Apple of AppleVariety | Banana of BananaVariety | Cherry of CherryVariety
  134. 134. Real world example of type composition
  135. 135. Example of some requirements: We accept three forms of payment: Cash, Check, or Card. For Cash we don't need any extra information For Checks we need a check number For Cards we need a card type and card number
  136. 136. interface IPaymentMethod {..} class Cash() : IPaymentMethod {..} class Check(int checkNo): IPaymentMethod {..} class Card(string cardType, string cardNo) : IPaymentMethod {..} In C# you would probably implement it as an interface and a set of subclasses, like this:
  137. 137. type CheckNumber = int type CardNumber = string In F# you would probably implement by composing types, like this
  138. 138. type CheckNumber = int type CardNumber = string type CardType = Visa | Mastercard type CreditCardInfo = CardType * CardNumber
  139. 139. type CheckNumber = int type CardNumber = string type CardType = Visa | Mastercard type CreditCardInfo = CardType * CardNumber type PaymentMethod = | Cash | Check of CheckNumber | Card of CreditCardInfo
  140. 140. type CheckNumber = int type CardNumber = string type CardType = Visa | Mastercard type CreditCardInfo = CardType * CardNumber type PaymentMethod = | Cash | Check of CheckNumber | Card of CreditCardInfo type PaymentAmount = decimal type Currency = EUR | USD
  141. 141. type CheckNumber = int type CardNumber = string type CardType = Visa | Mastercard type CreditCardInfo = CardType * CardNumber type PaymentMethod = | Cash | Check of CheckNumber | Card of CreditCardInfo type PaymentAmount = decimal type Currency = EUR | USD type Payment = { Amount : PaymentAmount Currency: Currency Method: PaymentMethod }
  142. 142. F# design principle: Types are executable documentation
  143. 143. type Deal = Deck –› (Deck * Card) type PickupCard = (Hand * Card) –› Hand Types are executable documentation type Suit = Club | Diamond | Spade | Heart type Rank = Two | Three | Four | Five | Six | Seven | Eight | Nine |Ten | Jack | Queen | King | Ace type Card = Suit * Rank type Hand = Card list type Deck = Card list type Player = {Name:string; Hand:Hand} type Game = {Deck:Deck; Players: Player list} The domain on one screen!
  144. 144. Types are executable documentation type CardType =Visa | Mastercard type CardNumber = CardNumber of string type CheckNumber = CheckNumber of int type PaymentMethod = | Cash | Check of CheckNumber | Card of CardType * CardNumber
  145. 145. Another big topic and not enough time   More on DDD and designing with types at fsharpforfunandprofit.com/ddd
  146. 146. INTERACTIVITY
  147. 147. Interactivity demo
  148. 148. Slides and video here F# consulting fsharpforfunandprofit.com/csharp F# for C# programmers

×