F# Training
F# Training
F# Training
  • Presentation
  • Fundamentals
    • Introduction
    • Syntax
      • Bases
      • Functions
      • Rules
      • Exceptions
    • First concepts
    • πŸ”Quiz
  • Functions
    • Signature
    • Concepts
    • Syntax
    • Standard functions
    • Operators
    • Addendum
    • πŸ”Quiz
    • πŸ“œSummary
  • Types
    • Overview
    • Tuples
    • Records
    • Unions
    • Enums
    • Anonymous records
    • Value types
    • πŸ“œRecap
    • Addendum
  • Monadic types
    • Intro
    • Option type
    • Result type
    • Smart constructor
    • πŸš€Computation expression (CE)
    • πŸš€CE theoretical basements
    • πŸ“œRecap
  • Pattern matching
    • Patterns
    • Match expression
    • Active patterns
    • πŸš€Fold function
    • πŸ“œRecap
    • πŸ•ΉοΈExercises
  • Collections
    • Overview
    • Types
    • Common functions
    • Dedicated functions
    • πŸ”Quiz
    • πŸ“œRecap
  • Asynchronous programming
    • Asynchronous workflow
    • Interop with .NET TPL
    • πŸ“œRecap
  • Module and Namespace
    • Overview
    • Namespace
    • Module
    • πŸ”Quiz
    • πŸ“œRecap
  • Object-oriented
    • Introduction
    • Members
    • Type extensions
    • Class, Struct
    • Interface
    • Object expression
    • Recommendations
Powered by GitBook
On this page
  • Purpose
  • Encapsulate the state in a type
  • Example #1
  • Example #2

Was this helpful?

Edit on GitHub
  1. Monadic types

Smart constructor

PreviousResult typeNextComputation expression (CE)

Last updated 1 month ago

Was this helpful?

Purpose

πŸ”— , Fβ™― for fun and profit

  • Design to prevent invalid states

    • Encapsulate state (all primitives) in an object

  • Smart constructor guarantees a valid initial state

    • Validates input data

    • If Ko, returns "nothing" (Option) or an error (Result)

    • If Ok, returns the created object wrapped in an Option / a Result

Encapsulate the state in a type

β†’ Single-case (discriminated) union: Type X = private X of a: 'a... πŸ”— , Fβ™― for fun and profit

β†’ Record: Type X = private { a: 'a... } πŸ”— , by Paul Blasucci

☝ private keyword:

  • Hide object content

  • Fields and constructor no longer visible from outside

  • Smart constructor defined in companion module or static method

Example #1

Smart constructor : β†’ tryCreate function in companion module β†’ Returns an Option

module Xxx.Types                            // πŸ‘ˆ Top-level module❗

type Latitude = private { Latitude: float } with
    member this.Value = this.Latitude       // πŸ‘ˆ Required because `.Latitude` is private too

[<RequireQualifiedAccess>]                  // πŸ‘ˆ Optional but recommended
module Latitude =
    let tryCreate (latitude: float) =
        if latitude >= -90. && latitude <= 90. then
            Some { Latitude = latitude }    // πŸ‘ˆ Constructor accessible here
        else
            None

Usages:

module Xxx.Usages

open Xxx.Types

let lat_ok = Latitude.tryCreate 45.  // Some { Latitude = 45.0 }
let lat_ko = Latitude.tryCreate 115. // None

Access control

private keyword has not exactly the same meaning in Fβ™― as in Cβ™―!

  • In Fβ™―, private indicates that the entity can be accessed only from the enclosing type or module.

  • In our example, private is applied on the Latitude definition that is on the Xxx.Types module.

  • { Latitude = ... } and latitude.Latitude are accessible in Xxx.Types module as if there were no private keyword.

  • In the 2nd code block, we are in another module. The Latitude definition is not accessible.

  • We can use only Latitude.tryCreate and latitude.Value.

Example #2

Smart constructor with:

  • Static method Of

  • Returns a Result with a string in the Error track.

type Tweet =
    private { Tweet: string }

    static member Of tweet =
        if System.String.IsNullOrEmpty tweet then
            Error "Tweet shouldn't be empty"
        elif tweet.Length > 280 then
            Error "Tweet shouldn't contain more than 280 characters"
        else Ok { Tweet = tweet }

let tweet1 = Tweet.Of "Hello world" // Ok { Tweet = "Hello world" }
Making illegal states unrepresentable
Designing with types: Single case union types
You Really Wanna Put a Union There? You Sure?