This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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? | |
*) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(* 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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(* 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>) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 () |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module EmployeeLocation | |
open TypeEquality | |
type Name = string | |
/// Some employees are engineers. | |
type Engineer = Engineer of Name | |
/// Some employees are factory workers. |
NewerOlder