Skip to content

Instantly share code, notes, and snippets.

@Savelenko
Savelenko / Zipper.fs
Last active January 26, 2024 08:51
Family tree zipper example
module Zipper
type Person = { Name : string; Children : List<Person> }
type Parent = Parent of {| Name : string; OtherChildren : List<Person> |} // Note *other* children
/// The "family tree" zipper
type FamilyTree = FamilyTree of Person * List<Parent> // A person and his/her ancestors
/// Person -> FamilyTree
@Savelenko
Savelenko / EarlyReturnAsync.fs
Created September 29, 2023 10:42
Async with early return capability CE for F#
(* Library portion *)
/// Just like Async but supports early return with skipping the rest of computations.
type ContAsync<'r,'a> = ('a -> Async<'r>) -> Async<'r>
/// Early return.
let early (a : 'a) : ContAsync<'a,_> = fun _ -> async { return a }
/// Computation expression builder.
@Savelenko
Savelenko / EarlyReturnExperiment.fs
Created September 28, 2023 14:26
Early return computation expression in F#
(* An experiment with implementing early return in F#. Initial examples work, but I do not know whether it is really correct! *)
/// A computation which runs to completion and produces 'r or returns an 'a early, short-circuiting some steps.
type R<'a,'r> =
private
| Done of 'r
| EarlyReturn of 'a
| Zero
| Effect of (unit -> R<'a,'r>)
@Savelenko
Savelenko / RankNExample.fs
Created September 25, 2023 10:04
When a HOF breaks in F#
// A polymorphic function which works for values of *any* type.
let hello (a : 't) : string =
// Just ignore the argument
"Hello"
// We can use it any context, on any input: it is polymorphic after all.
let result =
let a = hello 1
let b = hello "string"
@Savelenko
Savelenko / FactoryDemo.fs
Created September 25, 2023 09:06
Polymorphic factory methods
type Factory<'T> = unit -> Option<'T>
type NoOptionFactory<'T> = unit -> 'T
type FactoryTests () =
member _.CanFactory () =
// Use the Option-returning factory
let factory : Factory<'T> = FactoryTests.FactoryFunction
let testString : Option<string> = factory ()
let testInt : Option<int> = factory ()
@Savelenko
Savelenko / Example.cs
Created September 7, 2023 09:15
LINQ-to-nothing-special
private static void Main(string[] args)
{
/* LINQ-to-nothing-special */
Just<int> five = 5;
Just<int> six = 6;
var eleven = from a in five
from b in six
select a + b;
@Savelenko
Savelenko / Mendler.fs
Created April 27, 2023 10:01
Pretty printing trees in F# using a Mendler-style catamorphism
/// Non-empty trees.
type Tree<'a> = TreeNode of 'a * List<Tree<'a>>
/// Syntactic simulation of the `Tree` base functor.
let (|TreeNode_|) (a, ys) = (a, ys)
/// Regular catamorphism for `Tree`.
let rec cata f (TreeNode (a, ts)) = f a (ts |> List.map (cata f))
/// Compute a result from a single `Tree` node while having access to a function which computes a result from a single
@Savelenko
Savelenko / MeetingLocation.fs
Last active March 17, 2023 09:13
Meetings and locations model using simulated GADTs in F#
module EmployeeLocation
open TypeEquality
type Name = string
/// Some employees are engineers.
type Engineer = Engineer of Name
/// Some employees are factory workers.
@Savelenko
Savelenko / Bounded.fs
Last active December 21, 2022 15:44
Representing statically bounded values in F#
module Bounded =
type IBound =
static abstract Bound : int
type Bounded = private Bounded of int // Abstract data type
let bounded<'bound when 'bound :> IBound> (value : int) : Option<Bounded> =
if value <= 'bound.Bound then Some (Bounded value) else None
@Savelenko
Savelenko / Handler.fs
Created October 27, 2022 08:53
Experimental typed and computation expression-based Giraffe HTTP handlers
module Handler
open System.Threading.Tasks
open Giraffe
open Giraffe.FormatExpressions
open Microsoft.AspNetCore.Http
open Microsoft.Extensions.Logging
(* Core definitions *)