val createReservation : reservation:'a -> 'b
Full name: index.createReservation
val reservation : 'a
val createReservation : (obj -> obj)
Full name: index.createReservation
val validate : ('a -> 'b)
Full name: index.validate
val f : ('a -> 'b)
Full name: index.f
val g : ('b -> 'c)
Full name: index.g
val h : (obj -> obj)
Full name: index.h
type 'T option = Option<'T>
Full name: Microsoft.FSharp.Core.option<_>
val persist : ('a -> 'b)
Full name: index.persist
val persist' : ('a -> 'b)
Full name: index.persist'
val persist' : (obj option -> obj option)
Full name: index.persist'
module Option
from Microsoft.FSharp.Core
val bind : binder:('T -> 'U option) -> option:'T option -> 'U option
Full name: Microsoft.FSharp.Core.Option.bind
val bind : binder:('a -> 'b option) -> option:'a option -> 'b option
Full name: index.bind
val binder : ('a -> 'b option)
Multiple items
val option : 'a option
--------------------
type 'T option = Option<'T>
Full name: Microsoft.FSharp.Core.option<_>
union case Option.Some: Value: 'T -> Option<'T>
val value : 'a
union case Option.None: Option<'T>
val sendNotification' : (obj option -> obj option)
Full name: index.sendNotification'
val map : mapping:('T -> 'U) -> option:'T option -> 'U option
Full name: Microsoft.FSharp.Core.Option.map
val map : mapping:('a -> 'b) -> option:'a option -> 'b option
Full name: index.map
val mapping : ('a -> 'b)
        
        
            
Railway Oriented Programming
Functional approach to error handling
Happy path
Surely this is all that can happen...
Imperative example
| 1: 
2: 
3: 
4: 
5: 
6: 
 | public IHttpActionResult CreateReservation(ReservationDTO reservation) {
    Validate(reservation);
    PersistAndUpdate(reservation);
    SendNotification(reservation);
    return Json(reservation);
}
 | 
Functional example
| 1: 
2: 
3: 
4: 
5: 
 | let createReservation reservation =
    validate reservation
    |> persistAndUpdate
    |> sendNotification
    |> Json
 | 
Let's aim for point-free
| 1: 
2: 
3: 
4: 
5: 
 | let createReservation =
    validate
    >> persistAndUpdate
    >> sendNotification
    >> Json
 | 
But we can't have nice things
- Validations fail
- DB connections drop
- SMTP servers get overloaded
Imperative
| 1: 
2: 
3: 
4: 
5: 
6: 
 | public IHttpActionResult CreateReservation(ReservationDTO reservation) {
    Validate(reservation);
    PersistAndUpdate(reservation);
    SendNotification(reservation);
    return Json(reservation);
}
 | 
Imperative
| 1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
9: 
 | public IHttpActionResult CreateReservation(ReservationDTO reservation) {
    var validated = Validate(reservation);
    if (!validated) {
        return BadRequest("Reservation invalid!");
    }
    PersistAndUpdate(reservation);
    SendNotification(reservation);
    return Json(reservation);
}
 | 
Imperative
|  1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
 | public IHttpActionResult CreateReservation(ReservationDTO reservation) {
    var validated = Validate(reservation);
    if (!validated) {
        return BadRequest("Reservation invalid!");
    }
    var updatedReservation = PersistAndUpdate(reservation);
    if (updatedReservation == null) {
        return BadRequest("Unable to persist reservation!");
    }
    SendNotification(updatedReservation);
    return Json(reservation);
}
 | 
Imperative
|  1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
 | public IHttpActionResult CreateReservation(ReservationDTO reservation) {
    var validated = Validate(reservation);
    if (!validated) {
        return BadRequest("Reservation invalid!");
    }
    try {
        var updatedReservation = PersistAndUpdate(reservation);
        if (updatedReservation == null) {
            return BadRequest("Unable to update reservation!");
        }
    } catch {
        return InternalServerError("DB error: unable to persist reservation!");
    }
    SendNotification(updatedReservation);
    return Json(updatedReservation);
}
 | 
Imperative
|  1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
 | public IHttpActionResult CreateReservation(ReservationDTO reservation) {
    var validated = Validate(reservation);
    if (!validated) {
        return BadRequest("Reservation invalid!");
    }
    try {
        var updatedReservation = PersistAndUpdate(reservation);
        if (updatedReservation == null) {
            return BadRequest("Unable to update reservation!");
        }
    } catch {
        return InternalServerError("DB error: unable to persist reservation!");
    }
    try {
        SendNotification(updatedReservation);
    } catch {
        log.Error("Confirmation not sent!");
    }
    return Json(updatedReservation);
}
 | 
Functional?
| 1: 
2: 
3: 
4: 
5: 
 | let createReservation =
    validate
    >> persistAndUpdate
    >> sendNotification
    >> respond
 | 
What does any of this have to do with railways?
| 1: 
2: 
 | let f: 'a -> 'b = ...
let g: 'b -> 'c = ...
 | 

| 1: 
2: 
3: 
 | let f: 'a -> 'b = ...
let g: 'b -> 'c = ...
let h = f >> g
 | 

| 1: 
 | let h: 'a -> 'c = f >> g
 | 

Switches

| 1: 
2: 
 | let validate: Reservation -> Reservation option = ...
let persist:  Reservation -> Reservation option = ...
 | 

| 1: 
2: 
 | let validate: Reservation        -> Reservation option = ...
let persist': Reservation option -> Reservation option = ...
 | 

| 1: 
2: 
 | let persist': Reservation option -> Reservation option = 
    Option.bind persist
 | 

| 1: 
2: 
3: 
4: 
 | let bind binder option =
    match option with
    | Some value -> binder value
    | None -> None
 | 
| 1: 
2: 
 | let sendNotification': Reservation option -> Reservation option = 
    Option.map sendNotification
 | 

| 1: 
2: 
3: 
4: 
 | let map mapping option =
    match option with
    | Some value -> Some (mapping value)
    | None -> None
 | 
And many more...
- unit-returning functions
- exception-throwing functions
- inspections
- ...
Functional "real path"
| 1: 
2: 
3: 
4: 
5: 
 | let createReservation =
    validate
    >> persistAndUpdate
    >> sendNotification
    >> respond
 | 
Result<'TSuccess, 'TError> in FSharp.Core 4.1 (coming soon)