From dependency injection to dependency rejection Mark Seemann

  • Slides: 119
Download presentation
From dependency injection to dependency rejection Mark Seemann http: //blog. ploeh. dk @ploeh

From dependency injection to dependency rejection Mark Seemann http: //blog. ploeh. dk @ploeh

@ploeh

@ploeh

Object-oriented Functional ? @ploeh

Object-oriented Functional ? @ploeh

Functional un No tf Dependency injection ct io na l Object-oriented Partial application Composition

Functional un No tf Dependency injection ct io na l Object-oriented Partial application Composition @ploeh

Dependency injection is “really just a pretentious way to say ‘taking an argument’” -

Dependency injection is “really just a pretentious way to say ‘taking an argument’” - Rúnar Bjarnason (@runarorama) @ploeh

Example Restaurant Reservation @ploeh

Example Restaurant Reservation @ploeh

Restaurant Reservation Make a reservation Date Name Email Quantity Submit @ploeh

Restaurant Reservation Make a reservation Date Name Email Quantity Submit @ploeh

Restaurant Reservation Make a reservation Date 2 Name Email Quantity Submit @ploeh

Restaurant Reservation Make a reservation Date 2 Name Email Quantity Submit @ploeh

Restaurant Reservation Make a reservation Date 20 Name Email Quantity Submit @ploeh

Restaurant Reservation Make a reservation Date 20 Name Email Quantity Submit @ploeh

Restaurant Reservation Make a reservation Date 201 Name Email Quantity Submit @ploeh

Restaurant Reservation Make a reservation Date 201 Name Email Quantity Submit @ploeh

Restaurant Reservation Make a reservation Date 2016 Name Email Quantity Submit @ploeh

Restaurant Reservation Make a reservation Date 2016 Name Email Quantity Submit @ploeh

Restaurant Reservation Make a reservation Date 2016 Name Email Quantity Submit @ploeh

Restaurant Reservation Make a reservation Date 2016 Name Email Quantity Submit @ploeh

Restaurant Reservation Make a reservation Date 2016 -1 Name Email Quantity Submit @ploeh

Restaurant Reservation Make a reservation Date 2016 -1 Name Email Quantity Submit @ploeh

Restaurant Reservation Make a reservation Date 2016 -12 Name Email Quantity Submit @ploeh

Restaurant Reservation Make a reservation Date 2016 -12 Name Email Quantity Submit @ploeh

Restaurant Reservation Make a reservation Date 2016 -12 Name Email Quantity Submit @ploeh

Restaurant Reservation Make a reservation Date 2016 -12 Name Email Quantity Submit @ploeh

Restaurant Reservation Make a reservation Date 2016 -12 -2 Name Email Quantity Submit @ploeh

Restaurant Reservation Make a reservation Date 2016 -12 -2 Name Email Quantity Submit @ploeh

Restaurant Reservation Make a reservation Date 2016 -12 -29 Name Email Quantity Submit @ploeh

Restaurant Reservation Make a reservation Date 2016 -12 -29 Name Email Quantity Submit @ploeh

Restaurant Reservation Make a reservation Date 2016 -12 -29 Name M Email Quantity Submit

Restaurant Reservation Make a reservation Date 2016 -12 -29 Name M Email Quantity Submit @ploeh

Restaurant Reservation Make a reservation Date 2016 -12 -29 Name Ma Email Quantity Submit

Restaurant Reservation Make a reservation Date 2016 -12 -29 Name Ma Email Quantity Submit @ploeh

Restaurant Reservation Make a reservation Date 2016 -12 -29 Name Mar Email Quantity Submit

Restaurant Reservation Make a reservation Date 2016 -12 -29 Name Mar Email Quantity Submit @ploeh

Restaurant Reservation Make a reservation Date 2016 -12 -29 Name Mark Email Quantity Submit

Restaurant Reservation Make a reservation Date 2016 -12 -29 Name Mark Email Quantity Submit @ploeh

Restaurant Reservation Make a reservation Date 2016 -12 -29 Name Mark Email Quantity Submit

Restaurant Reservation Make a reservation Date 2016 -12 -29 Name Mark Email Quantity Submit @ploeh

Restaurant Reservation Make a reservation Date 2016 -12 -29 Name Mark S Email Quantity

Restaurant Reservation Make a reservation Date 2016 -12 -29 Name Mark S Email Quantity Submit @ploeh

Restaurant Reservation Make a reservation Date 2016 -12 -29 Name Mark Se Email Quantity

Restaurant Reservation Make a reservation Date 2016 -12 -29 Name Mark Se Email Quantity Submit @ploeh

Restaurant Reservation Make a reservation Date 2016 -12 -29 Name Mark See Email Quantity

Restaurant Reservation Make a reservation Date 2016 -12 -29 Name Mark See Email Quantity Submit @ploeh

Restaurant Reservation Make a reservation Date 2016 -12 -29 Name Mark Seem Email Quantity

Restaurant Reservation Make a reservation Date 2016 -12 -29 Name Mark Seem Email Quantity Submit @ploeh

Restaurant Reservation Make a reservation Date 2016 -12 -29 Name Mark Seema Email Quantity

Restaurant Reservation Make a reservation Date 2016 -12 -29 Name Mark Seema Email Quantity Submit @ploeh

Restaurant Reservation Make a reservation Date 2016 -12 -29 Name Mark Seeman Email Quantity

Restaurant Reservation Make a reservation Date 2016 -12 -29 Name Mark Seeman Email Quantity Submit @ploeh

Restaurant Reservation Make a reservation Date 2016 -12 -29 Name Mark Seemann Email Quantity

Restaurant Reservation Make a reservation Date 2016 -12 -29 Name Mark Seemann Email Quantity Submit @ploeh

Restaurant Reservation Make Date Name Email Quantity a reservation 2016 -12 -29 Mark Seemann

Restaurant Reservation Make Date Name Email Quantity a reservation 2016 -12 -29 Mark Seemann ma Submit @ploeh

Restaurant Reservation Make Date Name Email Quantity a reservation 2016 -12 -29 Mark Seemann

Restaurant Reservation Make Date Name Email Quantity a reservation 2016 -12 -29 Mark Seemann mar Submit @ploeh

Restaurant Reservation Make Date Name Email Quantity a reservation 2016 -12 -29 Mark Seemann

Restaurant Reservation Make Date Name Email Quantity a reservation 2016 -12 -29 Mark Seemann mark Submit @ploeh

Restaurant Reservation Make Date Name Email Quantity a reservation 2016 -12 -29 Mark Seemann

Restaurant Reservation Make Date Name Email Quantity a reservation 2016 -12 -29 Mark Seemann mark@ Submit @ploeh

Restaurant Reservation Make Date Name Email Quantity a reservation 2016 -12 -29 Mark Seemann

Restaurant Reservation Make Date Name Email Quantity a reservation 2016 -12 -29 Mark Seemann mark@p Submit @ploeh

Restaurant Reservation Make Date Name Email Quantity a reservation 2016 -12 -29 Mark Seemann

Restaurant Reservation Make Date Name Email Quantity a reservation 2016 -12 -29 Mark Seemann mark@pl Submit @ploeh

Restaurant Reservation Make Date Name Email Quantity a reservation 2016 -12 -29 Mark Seemann

Restaurant Reservation Make Date Name Email Quantity a reservation 2016 -12 -29 Mark Seemann mark@plo Submit @ploeh

Restaurant Reservation Make Date Name Email Quantity a reservation 2016 -12 -29 Mark Seemann

Restaurant Reservation Make Date Name Email Quantity a reservation 2016 -12 -29 Mark Seemann mark@ploe Submit @ploeh

Restaurant Reservation Make Date Name Email Quantity a reservation 2016 -12 -29 Mark Seemann

Restaurant Reservation Make Date Name Email Quantity a reservation 2016 -12 -29 Mark Seemann mark@ploeh Submit @ploeh

Restaurant Reservation Make Date Name Email Quantity a reservation 2016 -12 -29 Mark Seemann

Restaurant Reservation Make Date Name Email Quantity a reservation 2016 -12 -29 Mark Seemann mark@ploeh. Submit @ploeh

Restaurant Reservation Make Date Name Email Quantity a reservation 2016 -12 -29 Mark Seemann

Restaurant Reservation Make Date Name Email Quantity a reservation 2016 -12 -29 Mark Seemann mark@ploeh. d Submit @ploeh

Restaurant Reservation Make Date Name Email Quantity a reservation 2016 -12 -29 Mark Seemann

Restaurant Reservation Make Date Name Email Quantity a reservation 2016 -12 -29 Mark Seemann mark@ploeh. dk Submit @ploeh

Restaurant Reservation Make a reservation Date 2016 -12 -29 Name Mark Seemann JSON POST

Restaurant Reservation Make a reservation Date 2016 -12 -29 Name Mark Seemann JSON POST Email mark@ploeh. dk Quantity 4 Submit @ploeh

Restaurant Reservation Make Date Name Email Quantity a reservation 2016 -12 -29 Mark Seemann

Restaurant Reservation Make Date Name Email Quantity a reservation 2016 -12 -29 Mark Seemann mark@ploeh. dk 4 Submit POST JSON @ploeh

Validate Get reserved seats from DB Decide Create response Save reservation @ploeh

Validate Get reserved seats from DB Decide Create response Save reservation @ploeh

Object-oriented Dependency injection @ploeh

Object-oriented Dependency injection @ploeh

public class Reservations. Controller : Api. Controller { public Reservations. Controller(IValidator validator, IMapper mapper,

public class Reservations. Controller : Api. Controller { public Reservations. Controller(IValidator validator, IMapper mapper, IMaître. D maître. D) { this. validator = validator; POST /reservations HTTP/1. 1 this. mapper = mapper; this. maître. D = maître. D; { } "date": "2016 -12 -08", "name": "Mark Seemann", public IHttp. Action. Result Post(Reservation. Request. Dto dto) "email": "mark@ploeh. dk", { "quantity": 4 var validation. Msg = validator. Validate(dto); } if (validation. Msg != "") return this. Bad. Request(validation. Msg); var r = mapper. Map(dto); var id = maître. D. Try. Accept(r); if (id == null) return this. Status. Code(Http. Status. Code. Forbidden); return this. Ok(); } } @ploeh

public class Maître. D : IMaître. D { public Maître. D(int capacity, IReservations. Repository

public class Maître. D : IMaître. D { public Maître. D(int capacity, IReservations. Repository public interface reservations. Repository) IMaître. D { { this. capacity = capacity; int? Try. Accept(Reservation reservation); this. reservations. Repository = reservations. Repository; } } public int? Try. Accept(Reservation reservation) { var reserved. Seats = reservations. Repository. Read. Reservations(reservation. Date). Sum(r => r. Quantity); if (reserved. Seats + reservation. Quantity <= capacity) { reservation. Is. Accepted = true; return reservations. Repository. Create(reservation); } return null; } } @ploeh

How do I do dependency injection in Scala? Comic courtesy of @jrecursive and @hmemcpy

How do I do dependency injection in Scala? Comic courtesy of @jrecursive and @hmemcpy You don’t, because Scala is a functional language. @ploeh

Fine, it’s functional. How do I inject dependencies? Comic courtesy of @jrecursive and @hmemcpy

Fine, it’s functional. How do I inject dependencies? Comic courtesy of @jrecursive and @hmemcpy You use a Free Monad, which allows you to build a Monad from any Functor. @ploeh

Did you just tell me to go fuck myself? Comic courtesy of @jrecursive and

Did you just tell me to go fuck myself? Comic courtesy of @jrecursive and @hmemcpy I believe I did, Bob. @ploeh

Partial application An attempt at dependency injection with a functional language @ploeh

Partial application An attempt at dependency injection with a functional language @ploeh

Repository // int -> (Date. Time. Offset -> Reservation list) -> (Reservation -> int)

Repository // int -> (Date. Time. Offset -> Reservation list) -> (Reservation -> int) -> Reservation // -> int option let try. Accept capacity read. Reservations create. Reservation reservation = let reserved. Seats = read. Reservations reservation. Date |> List. sum. By (fun x -> x. Quantity) if reserved. Seats + reservation. Quantity <= capacity then create. Reservation { reservation with Is. Accepted = true } |> Some else None @ploeh

string -> Date. Time. Offset -> Reservation list // Reservation -> int option let

string -> Date. Time. Offset -> Reservation list // Reservation -> int option let try. Accept. Composition reservation = let read = DB. read. Reservations connection. String @ploeh

string -> Date. Time. Offset -> Reservation list // Reservation -> int option let

string -> Date. Time. Offset -> Reservation list // Reservation -> int option let try. Accept. Composition reservation = let read = DB. read. Reservations connection. String @ploeh

connection. String string -> Date. Time. Offset -> Reservation list // Reservation -> int

connection. String string -> Date. Time. Offset -> Reservation list // Reservation -> int option let try. Accept. Composition reservation = let read = DB. read. Reservations connection. String @ploeh

Date. Time. Offset -> Reservation list // Reservation -> int option let try. Accept.

Date. Time. Offset -> Reservation list // Reservation -> int option let try. Accept. Composition reservation = let read = DB. read. Reservations connection. String @ploeh

Reservation -> int // Reservation -> int option let try. Accept. Composition reservation =

Reservation -> int // Reservation -> int option let try. Accept. Composition reservation = let read = DB. read. Reservations connection. String let create = DB. create. Reservation connection. String try. Accept 10 read create reservation @ploeh

// Reservation -> int option let try. Accept. Composition reservation = let read =

// Reservation -> int option let try. Accept. Composition reservation = let read = DB. read. Reservations connection. String let create = DB. create. Reservation connection. String try. Accept 10 read create reservation @ploeh

// Reservation -> int option let try. Accept. Composition = let read = DB.

// Reservation -> int option let try. Accept. Composition = let read = DB. read. Reservations connection. String let create = DB. create. Reservation connection. String try. Accept 10 read create @ploeh

// Reservation -> int option let try. Accept. Composition = let read = DB.

// Reservation -> int option let try. Accept. Composition = let read = DB. read. Reservations connection. String let create = DB. create. Reservation connection. String try. Accept 10 read create @ploeh

IL @ploeh

IL @ploeh

internal class try. Accept. Composition@17 : FSharp. Func<Reservation, FSharp. Option<int>> { public int capacity;

internal class try. Accept. Composition@17 : FSharp. Func<Reservation, FSharp. Option<int>> { public int capacity; public FSharp. Func<Reservation, int> create. Reservation; public FSharp. Func<Date. Time. Offset, FSharp. List<Reservation>> read. Reservations; internal try. Accept. Composition@17( int capacity, FSharp. Func<Date. Time. Offset, FSharp. List<Reservation>> read. Reservations, FSharp. Func<Reservation, int> create. Reservation) { this. capacity = capacity; this. read. Reservations = read. Reservations; this. create. Reservation = create. Reservation; } public override FSharp. Option<int> Invoke(Reservation reservation) { return Maître. D. try. Accept<int>( this. capacity, this. read. Reservations, this. create. Reservation, reservation); } } @ploeh

Is it Functional? Partial application Dependency injection @ploeh

Is it Functional? Partial application Dependency injection @ploeh

Same return value for same input Pure function No sideeffects @ploeh

Same return value for same input Pure function No sideeffects @ploeh

Impure function Pure function @ploeh

Impure function Pure function @ploeh

Sanity check @ploeh

Sanity check @ploeh

Pure try. Accept : : Int -> (Zoned. Time -> [Reservation]) -> (Reservation ->

Pure try. Accept : : Int -> (Zoned. Time -> [Reservation]) -> (Reservation -> Int) -> Reservation -> Maybe Int try. Accept capacity read. Reservations create. Reservation reservation = let reserved. Seats = sum $ map quantity $ read. Reservations $ date reservation in if reserved. Seats + quantity reservation <= capacity then Just $ create. Reservation $ reservation { is. Accepted = True } else Nothing @ploeh

Zoned. Time -> IO [Reservation] Reservation -> IO Int le i try. Accept. Composition

Zoned. Time -> IO [Reservation] Reservation -> IO Int le i try. Accept. Composition : : Reservation p -> IO (Maybe Int) try. Accept. Composition reservation m = o connection. String let read = DB. read. Reservations c create = DB. create. Reservation connection. String t ’ in try. Accept 10 readn create reservation s e o D Zoned. Time -> [Reservation] Reservation -> Int @ploeh

Not Functional Partial application Dependency injection @ploeh

Not Functional Partial application Dependency injection @ploeh

@ploeh

@ploeh

Dependency injection makes everything impure @ploeh

Dependency injection makes everything impure @ploeh

Dependency Rejection @ploeh

Dependency Rejection @ploeh

Direct input Indirect input Unit Direct output Dependencies Indirect output @ploeh

Direct input Indirect input Unit Direct output Dependencies Indirect output @ploeh

Direct input Indirect input Unit Dependencies Direct output @ploeh

Direct input Indirect input Unit Dependencies Direct output @ploeh

// int -> (Date. Time. Offset -> Reservation list) -> (Reservation -> int) ->

// int -> (Date. Time. Offset -> Reservation list) -> (Reservation -> int) -> Reservation // -> int option let try. Accept capacity read. Reservations create. Reservation reservation = @ploeh

// int -> (Date. Time. Offset -> Reservation list) -> // -> Reservation option

// int -> (Date. Time. Offset -> Reservation list) -> // -> Reservation option let try. Accept capacity read. Reservations Reservation reservation = @ploeh

// int -> (Date. Time. Offset -> Reservation list) -> Reservation // -> Reservation

// int -> (Date. Time. Offset -> Reservation list) -> Reservation // -> Reservation option let try. Accept capacity read. Reservations reservation = @ploeh

// int -> (Date. Time. Offset -> Reservation list) -> Reservation option let try.

// int -> (Date. Time. Offset -> Reservation list) -> Reservation option let try. Accept capacity read. Reservations reservation = @ploeh

// int -> (Date. Time. Offset -> Reservation list) -> Reservation option let try.

// int -> (Date. Time. Offset -> Reservation list) -> Reservation option let try. Accept capacity read. Reservations reservation = let reserved. Seats = read. Reservations reservation. Date |> List. sum. By (fun x -> x. Quantity) if reserved. Seats + reservation. Quantity <= capacity then { reservation with Is. Accepted = true } |> Some else None @ploeh

// Reservation -> int option let try. Accept. Composition reservation = match try. Accept

// Reservation -> int option let try. Accept. Composition reservation = match try. Accept 10 (DB. read. Reservations connection. String) reservation with | None -> None | Some r -> (DB. create. Reservation connection. String) r |> Some @ploeh

// Reservation -> int option let try. Accept. Composition reservation = try. Accept 10

// Reservation -> int option let try. Accept. Composition reservation = try. Accept 10 (DB. read. Reservations connection. String) reservation |> Option. map (fun r -> DB. create. Reservation connection. String r) @ploeh

// Reservation -> int option let try. Accept. Composition reservation = try. Accept 10

// Reservation -> int option let try. Accept. Composition reservation = try. Accept 10 (DB. read. Reservations connection. String) reservation |> Option. map ( DB. create. Reservation connection. String ) @ploeh

// Reservation -> int option let try. Accept. Composition reservation = try. Accept 10

// Reservation -> int option let try. Accept. Composition reservation = try. Accept 10 (DB. read. Reservations connection. String) reservation |> Option. map (DB. create. Reservation connection. String) @ploeh

// Reservation -> int option let try. Accept. Composition reservation = reservation |> try.

// Reservation -> int option let try. Accept. Composition reservation = reservation |> try. Accept 10 (DB. read. Reservations connection. String) |> Option. map (DB. create. Reservation connection. String) @ploeh

Direct input Indirect input Unit Dependencies Direct output @ploeh

Direct input Indirect input Unit Dependencies Direct output @ploeh

Direct input Unit Dependencies Direct output @ploeh

Direct input Unit Dependencies Direct output @ploeh

// int -> (Date. Time. Offset -> Reservation list) -> Reservation option let try.

// int -> (Date. Time. Offset -> Reservation list) -> Reservation option let try. Accept capacity read. Reservations reservation = @ploeh

// int -> ( Reservation list) -> Reservation option let try. Accept capacity read.

// int -> ( Reservation list) -> Reservation option let try. Accept capacity read. Reservations reservation = @ploeh

// int -> Reservation list -> Reservation option let try. Accept capacity read. Reservations

// int -> Reservation list -> Reservation option let try. Accept capacity read. Reservations reservation = @ploeh

// int -> Reservation list -> Reservation option let try. Accept capacity rad. Reservations

// int -> Reservation list -> Reservation option let try. Accept capacity rad. Reservations reservation = @ploeh

// int -> Reservation list -> Reservation option let try. Accept capacity rd. Reservations

// int -> Reservation list -> Reservation option let try. Accept capacity rd. Reservations reservation = @ploeh

// int -> Reservation list -> Reservation option let try. Accept capacity r. Reservations

// int -> Reservation list -> Reservation option let try. Accept capacity r. Reservations reservation = @ploeh

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation = @ploeh

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation = @ploeh

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation = @ploeh

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation = @ploeh

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation = @ploeh

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation = @ploeh

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation = @ploeh

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation = @ploeh

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation = @ploeh

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation = @ploeh

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation = @ploeh

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation = @ploeh

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation = @ploeh

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation = @ploeh

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation = @ploeh

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation = @ploeh

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation = let reserved. Seats = reservations |> List. sum. By (fun x -> x. Quantity) if reserved. Seats + reservation. Quantity <= capacity then { reservation with Is. Accepted = true } |> Some else None @ploeh

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation

// int -> Reservation list -> Reservation option let try. Accept capacity reservations reservation = let reserved. Seats = reservations |> List. sum. By (fun x -> x. Quantity) if reserved. Seats + reservation. Quantity <= capacity then { reservation with Is. Accepted = true } |> Some else None @ploeh

// ('a -> 'b -> 'c) -> 'b -> 'a -> 'c let flip

// ('a -> 'b -> 'c) -> 'b -> 'a -> 'c let flip f x y = f y x // Reservation -> int option let try. Accept. Composition reservation = reservation. Date |> DB. read. Reservations connection. String |> fun reservations -> try. Accept 10 reservations reservation |> Option. map (DB. create. Reservation connection. String) @ploeh

// ('a -> 'b -> 'c) -> 'b -> 'a -> 'c let flip

// ('a -> 'b -> 'c) -> 'b -> 'a -> 'c let flip f x y = f y x // Reservation -> int option let try. Accept. Composition reservation = reservation. Date |> DB. read. Reservations connection. String |> fun reservations -> flip (try. Accept 10) reservations |> Option. map (DB. create. Reservation connection. String) @ploeh

// ('a -> 'b -> 'c) -> 'b -> 'a -> 'c let flip

// ('a -> 'b -> 'c) -> 'b -> 'a -> 'c let flip f x y = f y x // Reservation -> int option let try. Accept. Composition reservation = reservation. Date |> DB. read. Reservations connection. String |> -> flip (try. Accept 10) reservation |> Option. map (DB. create. Reservation connection. String) @ploeh

// ('a -> 'b -> 'c) -> 'b -> 'a -> 'c let flip

// ('a -> 'b -> 'c) -> 'b -> 'a -> 'c let flip f x y = f y x // Reservation -> int option let try. Accept. Composition reservation = reservation. Date |> DB. read. Reservations connection. String |> flip (try. Accept 10) reservation |> Option. map (DB. create. Reservation connection. String) @ploeh

Sanity check @ploeh

Sanity check @ploeh

try. Accept : : Int -> [Reservation] -> Reservation -> Maybe Reservation try. Accept

try. Accept : : Int -> [Reservation] -> Reservation -> Maybe Reservation try. Accept capacity reservations reservation = let reserved. Seats = sum $ map quantity reservations in if reserved. Seats + quantity reservation <= capacity then Just $ reservation { is. Accepted = True } else Nothing @ploeh

try. Accept. Composition : : Reservation -> IO (Maybe Int) try. Accept. Composition reservation

try. Accept. Composition : : Reservation -> IO (Maybe Int) try. Accept. Composition reservation = run. Maybe. T $ lift. IO (DB. read. Reservations connection. String $ date reservation) >>= Maybe. T. return. flip (try. Accept 10) reservation >>= lift. IO. DB. create. Reservation connection. String s le m o C i p @ploeh

Functional un No tf Dependency injection ct io na l Object-oriented Partial application Composition

Functional un No tf Dependency injection ct io na l Object-oriented Partial application Composition @ploeh

Mark Seemann http: //blog. ploeh. dk http: //bit. ly/ploehralsight @ploeh

Mark Seemann http: //blog. ploeh. dk http: //bit. ly/ploehralsight @ploeh