Skip to content

Instantly share code, notes, and snippets.

@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 / 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 / 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 / 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 / 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)
@Savelenko
Savelenko / Json.fs
Last active June 24, 2021 11:06
Church-encoded JSON in F#
/// Church-encoded JSON values.
type Json =
abstract Value<'r> :
(string -> 'r)
-> (bool -> 'r)
-> (decimal -> 'r)
-> (Map<string, Json> -> 'r)
-> (List<Json> -> 'r)
-> 'r
@Savelenko
Savelenko / Giraffe.purs
Created September 21, 2021 10:02
Giraffe computation expression (PureScript prototype)
module Giraffe where
import Prelude
import Control.Monad.Cont (Cont, callCC, cont, lift, runCont)
import Control.Monad.Reader (ReaderT, ask, runReaderT)
import Data.Maybe (Maybe(..))
data HttpContext = HttpContext
type HttpFuncResult = Maybe HttpContext -- Task<Option<..>> actually, but ignore Task for simplicity here
@Savelenko
Savelenko / Facility.fs
Created May 26, 2022 09:35
Error builder
module Facility
/// A facility which admits visitors (or does it?).
type Facility =
| BlackMesa
| DeathStar
| TeaHouse
(*