Skip to content

Instantly share code, notes, and snippets.

@Savelenko
Savelenko / GADTMotivation.fs
Last active June 4, 2024 14:40
Motivated simulation of GADTs in F#, quite motivational
module GADTMotivation
(*
Here is a simple motivational example for GADTs and their usefulness for library design and domain modeling. Suppose we
need to work with settings which can be displayed and adjusted in a GUI. The set of possible setting "types" is fixed
and known in advance: integers, strings and booleans (check-boxes).
The GUI should show an example value for each possible setting type, e.g. 1337 for an integer setting and "Hello" for a
string setting. How can we model this small domain of setting types and computing example values?
*)
@Savelenko
Savelenko / PhantomDemo.fs
Last active September 8, 2020 23:56
Phantom types with private representation
namespace PhantomTypes
module User =
type Username<'a> = private Username of string with
member u.Value = let (Username username) = u in username
type Short = interface end
type Full = interface end
@Savelenko
Savelenko / PhantomProof.fs
Last active August 25, 2022 13:39
Open phantom types with proof
namespace PhantomTypes
module Phantom =
// Private, so must use function 'prove'.
type ProofOf<'a> = private | ProofOfA
// A module proves that it can construct values of type 'a' by providing a value to this function.
let prove (_ : 'a) : ProofOf<'a> = ProofOfA
@Savelenko
Savelenko / ExistentialEngines.fs
Last active June 27, 2024 18:57
F# existential types
// The engine interface and helpers
type IEngine<'a,'b> =
abstract member Capacity : int // Does not depend on 'a or 'b; just an example
// Some other stuff here possible depending on 'a and 'b
/// A function which works on any engine polymorphically and returns a result of type 'r'. Needed because
/// F# does not support higher-ranked types (not the same as HKT!) in regular functions. This does work in members.
type EngineFunction<'r> =
abstract member Apply : IEngine<'a,'b> -> 'r
@Savelenko
Savelenko / TypeFamily.fs
Created November 25, 2020 14:42
What if F# had type families
(* What if F# had type families? *)
// We are a message processing system. There are regular and confidential messages to be delivered. Several delivery
// methods are supported. The main "business rule" is that regular messages must be sent by e-mail and confidential
// messages by post.
// Delivery methods.
type EMail = DeliveryMethodEmail of string
type Post = DeliveryMethodPost of {| RecipientName : string; Address : string |}
@Savelenko
Savelenko / TypeClasses.fs
Last active April 16, 2021 20:57
Intro to type classes using fantasy F# syntax
// Type classes (a.k.a. traits in Rust or protocols in Swift) are similar to interfaces. Main
// difference: an "implementation" can be provided separately from a type definition itself,
// retroactively. In this example using hypothetical F# syntax we both define TC and their
// implementations next to each other, but this is not required.
trait Equality<'a> with
equals : 'a -> 'a -> bool
// This definition says: "Type 'a belongs to a class (as in classification, characterization)
// of types which support equality. For every such type there is a function 'equals' with the
@Savelenko
Savelenko / Samples.fs
Last active April 4, 2021 15:46
F# GADT Sample model
module Samples
open TypeEquality
(* Generic data needed for all samples. *)
type Identifier = Identifier of int64
type Site = Site of string
// Together
@Savelenko
Savelenko / TransactionalApp.hs
Created April 27, 2021 09:49
Transactional
module TransactionalApp where
import Control.Monad.Writer
import Control.Monad.State
{- Model layer -}
data Account = Savings | Normal
deriving instance Eq Account
@Savelenko
Savelenko / FreeMonadPayment.hs
Last active May 19, 2021 06:18
Haskell free monad example
module FreeMonadPayment where
import Control.Monad.Free
import Control.Monad.Except
import Data.Text hiding (unpack)
import Control.Error
import Data.Function
import Data.Bifunctor
import Control.Newtype (unpack, Newtype)
@Savelenko
Savelenko / Program.fs
Last active June 13, 2021 14:41
Advanced(?) domain-driven design in F#
[<EntryPoint>]
let main argv =
printfn "Should be zero (netWeight emptyPallet): %A" Stock.shouldBeZero
printfn "harvesterPartsWeight: %A" Stock.harvesterPartsWeight
printfn "grossWeight harvesterParts: %A" (Stock.grossWeight Stock.harvesterParts)
printfn "grossWeight emptyPallet: %A" (Stock.grossWeight Stock.emptyPallet)
printfn "netWeight harvesterParts: %A" (Stock.netWeight Stock.harvesterParts)
printfn "value harvesterParts: %A" (Stock.value Stock.harvesterParts)
printfn "boxLabels harvesterParts: %A" (Stock.boxLabels Stock.harvesterParts)
printfn "boxLabels emptyPallet: %A" (Stock.boxLabels Stock.emptyPallet)