Being Functional 

take aways for my day to day code

@rhwy

Rui Carvalho

Student Talks

ncrafts.io

Agenda

we will talk about:

@rhwy

ncrafts.io

Why?

Ideas

Top Take aways

@rhwy

ncrafts.io

Why?

Open your minds!

@rhwy

ncrafts.io

01

why

PARADIGMS?

WHY ???

Today ...

@rhwy

ncrafts.io

$> OOP has been the de facto standard these last 20 years and a second nature for most developers 

$> rm -rf ~/

01

why

Long time ago ...

@rhwy

ncrafts.io

01

why

Each domain

has it's own solutions & paradigms!

@rhwy

ncrafts.io

Science

Bank

Artificial Intelligence

Fortran

Cobol

Prolog

01

why

Now ...

@rhwy

ncrafts.io

Everything is uniformized

bad object oriented programming everywhere

01

why

@rhwy

ncrafts.io

NO SILVER BULLET

 

Technology solve problems but it's not one to rule them all!

WHY BAD OOP ?

1/ well, there is 2 kinds of OOP ...

@rhwy

ncrafts.io

Data oriented

behavioural

01

why

WHY BAD OOP ?

1/ well, there is 2 kinds of OOP ...

@rhwy

ncrafts.io

Data oriented

behavioural

the basic idea of OOP is that objects encapsulate their concerns

better

worse

but today, most OO programs are built with anemic models ...

01

why

WHY BAD OOP ?

2/ Hell, do you know that object based programming is not the same as object oriented ?

@rhwy

ncrafts.io

Most apps I see are about procedural code within objects not OOP (polymorphism, inheritence, etc ...)

01

why

Procedural Objects     vs           OOP                    

@rhwy

ncrafts.io

01

why

public class MyProceduralApp   
{
    public double Execute(params string[] args)
    {
        if(args.Length < 3) throw new Exception("bad arguments");
        var command = args[0];
        var arguments = args.Skip(1);
        double result = 0;
        if(command == "add")
        {
            double a,b;
            if(double.TryParse(args[1],out a) 
                && double.TryParse(args[2], out b))
            {
                result = a+b;
            } else {
                throw new Exception("args 1 & 2 are not numbers");
            }
        }
        else if (command == "sub")
        {
            double a,b;
            if(double.TryParse(args[1],out a) 
                && double.TryParse(args[2], out b))
            {
                result = a-b;
            } else {
                throw new Exception("args 1 & 2 are not numbers");
            }
        }
        else if (command == "prod")
        {
            double a,b;
            if(double.TryParse(args[1],out a) 
                && double.TryParse(args[2], out b))
            {
                result = a*b;
            } else {
                throw new Exception("args 1 & 2 are not numbers");
            }
        }
        return result;
    }
}
public class MyBetterOOpApp {
    public double 
    ExecuteOperation (string operationName, double a, double b)
        => new Calculator().Execute(operationName,a,b);
}

public class Calculator {
    public IOperation GetOperatorFromName(string name) {
        switch (name)
        {
            case "add": return new AddOperation();
            case "sub": return new SubOperation();
            case "prod": return new ProdOperation();
            default: throw new Exception("bad operation name");
        }
    }
    public double Execute(string op, double left, double right)
    => GetOperatorFromName(op).Execute(left,right);
}

public interface IOperation {
    double Execute(double left, double right);
}

public class AddOperation : IOperation {
    public double Execute (double left, double right)
        => left + right;
}

public class SubOperation : IOperation {
    public double Execute (double left, double right)
    => left - right;
}

public class ProdOperation : IOperation {
    public double Execute (double left, double right)
    => left * right;
}
var result1 = new MyProceduralApp().Execute("add","1","2");
Console.WriteLine($"result 1+2= {result1}");

var result2 = new MyBetterOOpApp().ExecuteOperation("add",1,2);
Console.WriteLine($"result 1+2= {result2}");

@rhwy

ncrafts.io

Why?

you should have a deeper look into functional style even if you're doing procedural or object oriented programming

Concurrency, Parallelism

@rhwy

ncrafts.io

01

why

... and the limits of actual common programming

Moore's low is dead!

@rhwy

ncrafts.io

01

why

That means for the future:

many cores instead a new one, more powerful

@rhwy

ncrafts.io

~1970 -> ~2005

2 years

2 years

2 years

~2005 ->  ???

2 years

2 years

2 years

01

why

For the developper:

@rhwy

ncrafts.io

OOP

multi-threading

01

why

For the developper:

@rhwy

ncrafts.io

multi-threading

01

why

Complexity, problems

(mostly from shared states)

Functional

@rhwy

ncrafts.io

Functional programming means the lack of side effects

01

why

Safer parallel programming

But ...

@rhwy

ncrafts.io

Functional is not a silver bullet,

there is in all the cases limits to parallelism

01

why

Amdahl's Law

Speedup in latency of the execution of a program in function of the number of processors is limited by the serial part of the program

@rhwy

ncrafts.io

Why?

you should have a deeper look into functional style even if you're doing procedural or object oriented programming

01

Simplicity

@rhwy

ncrafts.io

understand : less bugs, better maintenance, easier evolution

01

why

Simplicity

@rhwy

ncrafts.io

Simpler structures & types

01

why

Simpler logic : one thing at a time

Simplified problem space : everything is a function!

Simplicity

@rhwy

ncrafts.io

01

why

Simplified problem space : everything is a function!

OOP

object Apple of abstract Fruit

Smoothie Factory

BlenderEngine for abstract Fruits

Generates

ProduceJuice method of abstract Juice

FP

Apple

Blend Function

input

object AppleJuice of abstract Juice

AppleJuice

output

Simplicity

@rhwy

ncrafts.io

01

why

Simplified problem space : everything is a function!

OOP

object Apple of abstract Fruit

Smoothie Factory

BlenderEngine for abstract Fruits

Generates

ProduceJuice method of abstract Juice

object AppleJuice of abstract Juice

let's do a cocktail now !

Alcool Builder

Build From AlcoolType

Rum

Cocktail Factory

generates

Apple Mojito builder

uses

uses

Build

more complex:

Apple Mojito

Simplicity

@rhwy

ncrafts.io

01

why

Simplified problem space : everything is a function!

FP

let's do a cocktail now !

more complex:

Apple

Blend Function

input

AppleJuice

output

Rum

Shaker Function

input

input

output

Apple Mojito

... and yes, I know, i'm judging and not totally partial

@rhwy

ncrafts.io

Why?

you should have a deeper look into functional style even if you're doing procedural or object oriented programming

01

Better Feedback loops

@rhwy

ncrafts.io

01

why

Better Feedback loops

@rhwy

ncrafts.io

REPL

as structures are simpler, quite all functional languages are provided with an interactive playground.

 

after playing with a repl, you’ll always miss one!

01

why

Better Feedback loops

@rhwy

ncrafts.io

By design

as functions are everywhere, everything is simpler and quicker to test

01

why

@rhwy

ncrafts.io

Ideas

02

Functional Programming

Is a paradigm

... and a different way of thinking about programs than the mainstream, imperative, mostly object oriented paradigms you're probably used to

02

ideas

Functional Programming

Functional programming is a style of programming that emphasizes the evaluation of expressions, rather than execution of commands.

 

The expressions in these languages are formed by using functions to combine basic values

02

ideas

Functional

Style of Programming

  • Functions that create other functions

  • The use of basic datatypes, notably maps

  • Trying to solve problems by setting up data that can be seen as flowing through functions

02

ideas

Functional

Style of Programming

Functions as first class citizens

02

ideas

Functions are top level constructs like classes in object oriented languages

Functions are usually grouped into modules

module Calculator

    function Add = (x,y) -> x + y 
public class Calculator {
    public static long Add (int x, int y) {
        return x+y
    }
}

Functional

Style of Programming

Use of simple data constructs (mostly)

02

ideas

there is 2 flavors of functional programming : the ones that are dynamically typed and the ones that provide strong typing

let message = ("hello","rui")
type word = string
type message = list of words
let greeting = ["hello", "word"]

dynamic -> better flexibility

great types -> better models, less errors

Functional

Style of Programming

manipulate data over a pipeline of functions

02

ideas

that's the general idea, we have functions everywhere and the output of one is the input of the next

let buildGreeting name = $"hello {name}, how are you?"
let splitWords sentence = String.split (sentence, " ")
let capitalizeFirstLetter list = Seq.map (
        word -> head(word).ToUpper() + tail(word) )
let buildFinalSentence list = Seq.join (list, " ")


let greetingsFor name = 
    buildGreeting 
    |> splitWords
    |> capitalizeFirstLetter
    |> buildFinalSentence

let message = greetingsFor "rui" 
//print : Hello Rui, How Are You?"

Functional

key concepts

02

ideas

Recursion

loops, storage

expressions

rather than statements

Algebraic types

for better models

Pattern Matching

for control flow

Pure functions

to avoid side effects

Immutability

for safety

Functional

key concepts

02

ideas

expressions

rather than statements

there is no statements, only expressions

every piece of code returns a value

like SQL

int result;
if( condition) {
    result = 42;
} else {
    result = -1;
}

statements style

int result =
    condition ? 42 : -1 ;

expression style

Functional

key concepts

02

ideas

Algebraic types

for better models

create complex models by combining simple types

new type = type1 AND type2

type BasketItem = { 
    name: string; 
    quantity: int}

let aBook = { 
    name="Dune"; 
    quantity=3}

 

new type = type1 OR  type2

type Card = 
    | Head of string
    | Number of int

let card1 = Head "King"
let card2 = Number 1

 

Functional

key concepts

02

ideas

Immutability

for safety

  • Immutable data makes the code predictable

  • Immutable data is easier to work with

  • Immutable data forces you to use a “transformational” approach

when a value is set, you can't change it !

Functional

key concepts

02

ideas

Pattern Matching

for control flow

usual forms of conditional expressions can be replaced by pattern matching

type Shape =     
    | Circle of radius:int 
    | Rectangle of height:int * width:int

let surface shape = 
    match shape with
    | Circle r -> r * r * 3.14
    | Rectangle (x,y) -> x * y

Functional

key concepts

02

ideas

Pure functions

to avoid side effects

evaluating the function

cannot possibly have any effect on the input, or anything else for that matter

// pure
let add x y = x + y

// not pure
let mutable counter = 0
let inc = counter + 1

Functional

key concepts

02

ideas

Pure functions

to avoid side effects

but with immutability and pure functions, how could I change data or do a for loop?

Immutability

for safety

Functional

key concepts

02

ideas

Recursion

loops, storage

let rec do5 action index = 
    action()
    if index < 5 
        return do5 action index+1
    else
        return "done!"

inception?

@rhwy

ncrafts.io

From ideas

to Take away

 (let's try to write real code from these ideas )

03

@rhwy

ncrafts.io

Take away #01

think in functions

03

take

=> Use Delegates to define your contracts

 

=> Use Lambdas to define your implementations

 

instead of interfaces when not needed

instead of class implementations when not needed

@rhwy

ncrafts.io

Take away #01

think in functions

03

take

  1. Use Delegates to define your contracts

  2. Use Lambdas to define your implementations

public interface IOperation {
    double Execute(long left, long right);
}
public class AddOperation : IOperation {
    public double Execute(long left, long right) {
        return left + right;
    }
} 
public class Calculator
{
    public double Execute(
        IOperation operation, long left, long right)
        => operation.Execute(left,right);
}

public class App
{
    public void Main() {
        var calculator = new Calculator();
        IOperation operation = new AddOperation();
        var result = calculator.Execute(operation,1,2);
        Console.Write($"1+2={result}");
    }
}
public delegate double 
    Operation(long left, long right);

public class Calculator {
    public static double Execute(
        Operation operation, long left, long right)
        => operation(left,right);
}
public class App {
    public void Main() {
        var result = Calculator.Execute( 
            (x,y) => x+y, 1, 2);
        Console.Write($"1+2={result}");
    }
}

from this to this

@rhwy

ncrafts.io

Take away #02

use pure static global functions

03

take

Text

if your functions have no state and no side effects it's ok to use static

that means that if you always have the same output for one output it can also be tested and used with confidence

public static class StringUtils {

    public static string CapitalizeFirst(string word)
        =>  word.Substring(0,1).ToUpper()
            + word.Substring(1).ToLower();

    public static string Line(int size, char element = '-')
        => new String(element,size);
}

@rhwy

ncrafts.io

Take away #02

use pure static global functions

03

take

it's even better if you can "import" the static class in your language

ex : in C# using static myclass allows you to play directly with static functions

public static class StringUtils {

    public static string CapitalizeFirst(string word)
        =>  word.Substring(0,1).ToUpper()
            + word.Substring(1).ToLower();

    public static string Line(int size, char element = '-')
        => new String(element,size);
}
using static System.Console;
using static GlobalFunctions.StringUtils;

public class RunDemo
{
    public static void Run()
    {
        WriteLine("Hello" + CapitalizeFirst("rui"));
        WriteLine(Line(80));
    }
}

@rhwy

ncrafts.io

Take away #03

use High Order Functions

03

take

a higher-order function (also functional, functional form or functor) is a function that does at least one of the following:

  • takes one or more functions as arguments
  • returns a function as its result

think in terms of (reusable) expressions instead of statements

simplifies decoupling

@rhwy

ncrafts.io

Take away #03

use High Order Functions

03

take

public static Func<string> GetIdGenerator()
{
    return ()=> Guid.NewGuid()
                    .ToString().Substring(0,8);
}

public static void PrintResult<T>(Func<T> action)
{
    T result = action();
    Console.WriteLine($"result = {result}");
}
Func<string> generateNewId = GetIdGenerator();

PrintResult(generateNewId);
PrintResult(generateNewId);

//result = ec1ed257
//result = ce36e7f7

your lib

usage

@rhwy

ncrafts.io

Take away #04

use Helpers to facilitate functions

03

take

a must have!

function declaration can sometimes be messy, take advantage of type inference!

Func<Tuple<int,int>,string,string> listToString1 = 

    (Tuple<int,int> t, string message) 
        => $"({message}{t.Item1},{t.Item2})";

don't work, you need to write this:

//because "Cannot assign lambda function to an implicit-typed variable"
var listToString1 = 
    (Tuple<int,int> t, string message) 
        => $"({message}{t.Item1},{t.Item2})";

@rhwy

ncrafts.io

Take away #04

use Helpers to facilitate functions

03

take

a must have!

with this small helper:

Func<Tuple<int,int>,string,string> listToString1 = 

    (Tuple<int,int> t, string message) 
        => $"({message}{t.Item1},{t.Item2})";

can be written like this :

public static Func<T1,T2> 
    fun<T1,T2>(Func<T1,T2> function) => function;
var tupleToString = fun( 
    (Tuple<int,int> t, string message) => $"({t.Item1},{t.Item2})");

@rhwy

ncrafts.io

Take away #05

compose workflow in functions

03

take

while procedural/objects are about statements, functional is about expressions and composition of expressions

 var dico = new Dictionary<int,string> {
      [1]="one",[2]="two",[3]="three"
        };
var list = new List<string>();
foreach(var item in dico)
{
    list.Add(item.Value);
}

var result = string.Empty;
foreach(var item in list)
{
    result += item + ",";
}
result = result.Substring(0,result.Length-1);

ex: take this procedural style code

@rhwy

ncrafts.io

Take away #05

compose workflow with functions

03

take

while procedural/objects are about statements, functional is about expressions and composition of expressions

public static Dictionary<int,string> 
    GetDico() => new Dictionary<int,string> {
                [1]="one",[2]="two",[3]="three"
            };
public static IEnumerable<U> DicoToList<T,U>
    (Dictionary<T,U> dico) => dico.Values;

public static string ConcatList
    (IEnumerable<string> list) => String.Join(",",list);

if you refactor it to functions

var dico = GetDico();
var list = DicoToList(dico);
var concatList1 = ConcatList(list);
WriteLine(concatList1);

you'll use it like this

much better!

@rhwy

ncrafts.io

Take away #05

compose workflow with functions

03

take

we would like to chain these functions to create a composition, but no pipes in OOP ;-(

//not working:
let concatList =
    GetDico()
    |> DicoToList
    |> ConcatList

we would like to write it like this

var concatList = 
    ConcatList(
        DicoToList(
            GetDico()));

but we can only compose like this:

@rhwy

ncrafts.io

Take away #05

compose workflow with functions

03

take

solution : another Helper!

public static U Then<T,U>
(this T current, Func<T,U> transform) 
    => transform(current);

and now we can write the full expression

//v3 = functional style : combine expressions:
WriteLine(
    GetDico()
    .Then(DicoToList)
    .Then(ConcatList));

@rhwy

ncrafts.io

Take away #06

handle errors with railway programming

03

take

at every statement step you must verify the result or catch the error, this will be quickly messy!

double Div(double a, double b) {
    if (b==0) throw new DivideByZeroException();
    return a/b;
}

string AddLabel(double number) {
    return $"value = {number.Value}";
}

try {
    var result = Div(1,0);
    var label = AddLabel(result);
    WriteLine(label);
} catch(Exception ex)
{
    WriteLine("error : " + ex.Message)
}

@rhwy

ncrafts.io

Take away #06

handle errors with railway programming

03

take

why not manage errors all along  transparentrly and unwrap thing only at the end?

Result<double> Div(double a, double b) {
    if (b==0) return new Failure<double>("divide by zero");
    return new Success(a/b);
}

Result<string> AddLabel(Result<double> number) {
    if(! number.IsSuccess) return new Failure<string>(number.Message);
    return $"value = {number.Value}";
}

Div(1,0)
    .Then(AddLabel)
    .Then( 
        success: label => WriteLine(label),
        failure: err => WriteLine("error : " + err.Message)

@rhwy

ncrafts.io

Take away #07

avoid void, always return something!

03

take

void are black holes where you'll be trapped, you don't know what can happened!

@rhwy

ncrafts.io

Take away #07 bis

avoid nulls

03

take

what is the percentage of your code where you are checking for the non-nullity of a variable ???

at least, use a default None value for your type

@rhwy

ncrafts.io

Take away #08

immutability

03

take

if a variable can't change, you couldn't have side effects!

because classes are reference types, think about using more enums & structs!

@rhwy

ncrafts.io

Take away #08

Recap

03

take

1. think in functions
2. use pure static global functions
3. use High Order Functions
4. use Helpers to facilitate functions
5. compose workflow with functions
6. handle errors with railway programming
7. avoid void, always return something!
7. avoid nulls
8. immutability

Thanks

@rhwy

ncrafts.io

http://github.com/rhwy/beingfunctional

sample code & slides

next NewCrafts conference: 

2017, 18-19 of May

Bonus Time

@rhwy

ncrafts.io

How does a web request should work?

components ?

JAVA JSF ?

ASP.NET WEBFORMS?

THE WEB IS FUNCTIONAL!

Response = f(request)

Request -> Async<Response>

Functional web

"hello world"

#r "packages/Suave/lib/net40/Suave.dll"
open Suave
startWebServer defaultConfig 
  (Successful.OK "Hello World!")

Being Functional

By Rui Carvalho

Being Functional

A little introduction to functional programming concepts for the procedural object oriented programmer with some concrete exemples on what you can use in your day to day code

  • 1,056