Skip to content

Instantly share code, notes, and snippets.

@palladin
palladin / UnFold.cs
Last active July 6, 2020 12:27
IAsyncEnumerable UnFold
static async IAsyncEnumerable<T> UnFold<T, TAcc>(Func<TAcc, Task<(bool Next, IAsyncEnumerable<T> Values, TAcc Acc)>> f, TAcc seed)
{
var acc = seed;
var result = default((bool Next, IAsyncEnumerable<T> Values, TAcc Acc));
do
{
result = await f(acc);
await foreach (var value in result.Values)
yield return value;
@palladin
palladin / knowthyself.cs
Created July 27, 2021 14:51
Know thyself
Expression<Func<Expression, Func<int, int>>> f =
self => x => ((Expression<Func<Expression, Func<int, int>>>)self).Compile()(self)(x + 1);
var x = f.Compile()(f)(0);
@palladin
palladin / maybe.cs
Last active September 25, 2021 17:42
Maybe monad
// https://blog.neteril.org/blog/2017/04/26/maybe-computation-expression-csharp/
[AsyncMethodBuilder(typeof(MaybeAsyncMethodBuilder<>))]
interface Option<T> { }
// Could use the closed type hierarchy Roslyn feature
// to be an approximation of a discriminated union
// https://github.com/dotnet/csharplang/issues/485
sealed class None<T> : Option<T> { public static readonly None<T> Value = new None<T>(); }
sealed class Some<T> : Option<T>
{
@palladin
palladin / gist:1085033
Created July 15, 2011 16:35
The repmin problem
// For more info
// http://www.springerlink.com/content/g74174vvl1861605/
// http://www.haskell.org/haskellwiki/Circular_programming
// Helper functions
let force (value : Lazy<_>) = value.Force()
let lazyMap f l = lazy (f (force l))
// Generic feedback loop function
let trace f input =
@palladin
palladin / gist:1085030
Created July 15, 2011 16:33
A Clojure inspired (race free) memoize function
// Info: http://clojure.org/atoms
open System
open System.Threading
type Atom<'T when 'T : not struct>(value : 'T) =
let refCell = ref value
let rec swap f =
let currentValue = !refCell
@palladin
palladin / gist:1085027
Created July 15, 2011 16:32
Clojure's Atoms
open System.Threading
type Atom<'T when 'T : not struct>(value : 'T) =
let refCell = ref value
let rec swap f =
let currentValue = !refCell
let result = Interlocked.CompareExchange<'T>(refCell, f currentValue, currentValue)
if obj.ReferenceEquals(result, currentValue) then ()
else Thread.SpinWait 20; swap f
@palladin
palladin / gist:1084722
Created July 15, 2011 13:46
Functional Unparsing SQL
// Functional Unparsing http://www.brics.dk/RS/98/12/BRICS-RS-98-12.pdf
open System
open System.Data
open System.Data.SqlClient
// Type Decls
type SqlText = string
type Counter = int
@palladin
palladin / gist:1084515
Created July 15, 2011 11:24
Actors acting as Lambdas
// Useful type aliases
type Actor = MailboxProcessor<obj>
type Ident = string
type Cond = Actor
type Env = Actor
let (<!>) (actor : Actor) (msg : 'T) = actor.Post msg
// run forever - template
@palladin
palladin / gist:1084511
Created July 15, 2011 11:21
Functional style Regex engine
let char c (s : string) = seq { if s.Length > 0 && s.[0] = c then yield s.Substring(1) }
let (=>) l r s = seq { for sl in l s do for sr in r sl -> sr }
let (<|>) l r s = seq { yield! l s; yield! r s }
let rec (<*>) e s = seq { yield s; yield! (e => (<*>) e) s }
let (<+>) e = e => (<*>) e
@palladin
palladin / gist:1084507
Created July 15, 2011 11:20
Norvig's Spelling Corrector
// Norvig's Spelling Corrector: http://norvig.com/spell-correct.html
open System.IO open System.Text.RegularExpressions
let edits1 (word : string) =
let splits = [for i in 0 .. word.Length do yield (word.[0..i-1], word.[i..])]
let deletes = [for a, b in splits do if b <> "" then yield a + b.[1..]]
let transposes = [for a, b in splits do if b.Length > 1 then yield a + string b.[1] + string b.[0] + b.[2..]]
let replaces = [for a, b in splits do for c in 'a'..'z' do if b <> "" then yield a + string c + b.[1..]]
let inserts = [for a, b in splits do for c in 'a'..'z' do yield a + string c + b]
deletes @ transposes @ replaces @ inserts |> Set.ofList