Header menu logo TDesu.FSharp

TDesu.FSharp Tutorial

Result: Railway-Oriented Programming

Chain operations that might fail. Short-circuits on first Error.

let validateAge age =
    if age < 0 then Error "age must be positive"
    elif age > 150 then Error "age too large"
    else Ok age

let validateName name =
    Result.requireNotNull "name is required" name
    |> Result.bind (fun n ->
        if String.IsNullOrWhiteSpace(n) then Error "name is empty"
        else Ok n)

// Pipeline: validate, transform, log
let processUser name age =
    validateName name
    |> Result.bind (fun n -> validateAge age |> Result.map (fun a -> n, a))
    |> Result.tee (fun (n, a) -> printfn "Valid: %s, %d" n a)
    |> Result.teeError (fun e -> printfn "Invalid: %s" e)

let valid = processUser "Alice" 30
Warning: Output, it-value and value references require --eval
let invalid = processUser "" -5
Warning: Output, it-value and value references require --eval

Option: Maybe Pipeline

Short-circuit on None. Great for lookups and parsing.

open TDesu.FSharp.MaybeBuilder

let tryFindUser (id: int) =
    if id > 0 then Some {| Name = "Alice"; Email = "alice@example.com" |}
    else None

let tryGetDomain email =
    match email |> String.split "@" with
    | [| _; domain |] -> Some domain
    | _ -> None

let userDomain = option {
    let! user = tryFindUser 1
    let! domain = tryGetDomain user.Email
    return domain
}
Warning: Output, it-value and value references require --eval

Parse Active Patterns

Match and extract typed values from strings in one step.

open TDesu.FSharp.ActivePatterns

let describe input =
    match input with
    | Parse.Int n -> sprintf "integer: %d" n
    | Parse.Double d -> sprintf "float: %f" d
    | Parse.Bool b -> sprintf "bool: %b" b
    | Parse.Guid g -> sprintf "guid: %A" g
    | other -> sprintf "text: %s" other

let examples = [ "42"; "3.14"; "true"; "hello" ] |> List.map describe
Warning: Output, it-value and value references require --eval

String Utilities

Pipeline-friendly string operations.

let processed =
    "  Hello, World!  "
    |> String.trim
    |> String.replace "World" "F#"
    |> String.toLowerInv
Warning: Output, it-value and value references require --eval
let parts = "one,two,three" |> String.split "," |> String.join " | "
Warning: Output, it-value and value references require --eval

ResizeArray: Functional Mutable Lists

Pipeable wrappers for System.Collections.Generic.List<T>.

let topScores =
    ResizeArray.create ()
    |> ResizeArray.add 95
    |> ResizeArray.add 42
    |> ResizeArray.add 88
    |> ResizeArray.add 73
    |> ResizeArray.filter (fun x -> x > 50)
    |> ResizeArray.sort
    |> ResizeArray.toArray
Warning: Output, it-value and value references require --eval

Guard: Validate-and-Throw

One-liner argument validation. Throws standard .NET exceptions.

let divide a b =
    Guard.positive "b" b
    a / b

try divide 10 0 |> ignore
with :? ArgumentOutOfRangeException as ex -> printfn "Caught: %s" ex.ParamName

Disposable Helpers

RAII patterns for F#.

// Go-style defer stack
let processFiles () =
    use cleanup = Disposable.deferStack ()
    let path, pathDispose = Disposable.tempFile ()
    cleanup.AddDisposable(pathDispose)
    printfn "Temp file: %s" path
    // cleanup runs on exit -- deletes temp file

// Combine multiple disposables
let combined = Disposable.combine [
    Disposable.create (fun () -> printfn "cleanup 1")
    Disposable.create (fun () -> printfn "cleanup 2")
]

Bytes & Hashing

Low-level buffer operations and content hashing.

let hash = ContentHash.sha256Hex "hello world"
Warning: Output, it-value and value references require --eval
let data1 = [| 1uy; 2uy |]
let data2 = [| 3uy; 4uy |]
let joined = Bytes.concat2 data1 data2
Warning: Output, it-value and value references require --eval
let dictKey = Hash.ofArray [| 1; 2; 3 |]
Warning: Output, it-value and value references require --eval

Bounded Collections

Auto-evict oldest when at capacity. Perfect for caches and dedup buffers.

let recentIds = BoundedDict<string, int>(3)
recentIds.Set("a", 1)
recentIds.Set("b", 2)
recentIds.Set("c", 3)
recentIds.Set("d", 4)  // "a" evicted
let hasA = recentIds.ContainsKey "a"
let hasD = recentIds.TryGet "d"
Warning: Output, it-value and value references require --eval Warning: Output, it-value and value references require --eval
namespace System
namespace TDesu
namespace TDesu.FSharp
namespace TDesu.FSharp.Buffers
namespace TDesu.FSharp.Hashing
namespace TDesu.FSharp.Resilience
val validateAge: age: int -> Result<int,string>
val age: int
union case Result.Error: ErrorValue: 'TError -> Result<'T,'TError>
union case Result.Ok: ResultValue: 'T -> Result<'T,'TError>
val validateName: name: string -> Result<string,string>
val name: string
Multiple items
module Result from TDesu.FSharp

--------------------
module Result from Microsoft.FSharp.Core

--------------------
[<Struct>] type Result<'T,'TError> = | Ok of ResultValue: 'T | Error of ErrorValue: 'TError
val requireNotNull: error: 'TError -> value: 'T -> Result<'T,'TError>
<summary> Returns Ok(value) if not null, Error(error) if null. &lt;param name="error"&gt;The error value to use when the value is null.&lt;/param&gt; &lt;param name="value"&gt;The value to check for null.&lt;/param&gt; </summary>
Multiple items
val bind: [<InlineIfLambda>] f: ('a -> Result<'b,'c>) -> r: Result<'a,'c> -> Result<'b,'c>
<summary> Chains a Result-returning function on Ok; short-circuits on Error. &lt;param name="f"&gt;The function returning a new Result.&lt;/param&gt; &lt;param name="r"&gt;The result to bind over.&lt;/param&gt; </summary>

--------------------
val bind: binder: ('T -> Result<'U,'TError>) -> result: Result<'T,'TError> -> Result<'U,'TError>
val n: string
Multiple items
type String = interface IEnumerable<char> interface IEnumerable interface ICloneable interface IComparable interface IComparable<string> interface IConvertible interface IEquatable<string> interface IParsable<string> interface ISpanParsable<string> new: value: nativeptr<char> -> unit + 8 overloads ...
<summary>Represents text as a sequence of UTF-16 code units.</summary>

--------------------
String(value: nativeptr<char>) : String
String(value: char array) : String
String(value: ReadOnlySpan<char>) : String
String(value: nativeptr<sbyte>) : String
String(c: char, count: int) : String
String(value: nativeptr<char>, startIndex: int, length: int) : String
String(value: char array, startIndex: int, length: int) : String
String(value: nativeptr<sbyte>, startIndex: int, length: int) : String
String(value: nativeptr<sbyte>, startIndex: int, length: int, enc: Text.Encoding) : String
String.IsNullOrWhiteSpace([<NotNullWhenAttribute (false)>] value: string) : bool
val processUser: name: string -> age: int -> Result<(string * int),string>
Multiple items
val map: [<InlineIfLambda>] f: ('a -> 'b) -> r: Result<'a,'c> -> Result<'b,'c>
<summary> Transforms the Ok value with f, passing Error through unchanged. &lt;param name="f"&gt;The mapping function to apply to the Ok value.&lt;/param&gt; &lt;param name="r"&gt;The result to transform.&lt;/param&gt; </summary>

--------------------
val map: mapping: ('T -> 'U) -> result: Result<'T,'TError> -> Result<'U,'TError>
val a: int
val tee: [<InlineIfLambda>] f: ('T -> unit) -> r: Result<'T,'TError> -> Result<'T,'TError>
<summary> Applies a side-effect on Ok and returns the result unchanged. &lt;param name="f"&gt;The side-effect function to apply on Ok.&lt;/param&gt; &lt;param name="r"&gt;The result to inspect.&lt;/param&gt; </summary>
val printfn: format: Printf.TextWriterFormat<'T> -> 'T
val teeError: [<InlineIfLambda>] f: ('TError -> unit) -> r: Result<'T,'TError> -> Result<'T,'TError>
<summary> Applies a side-effect on Error and returns the result unchanged. &lt;param name="f"&gt;The side-effect function to apply on Error.&lt;/param&gt; &lt;param name="r"&gt;The result to inspect.&lt;/param&gt; </summary>
val e: string
val valid: Result<(string * int),string>
val invalid: Result<(string * int),string>
val tryFindUser: id: int -> {| Email: string; Name: string |} option
val id: int
Multiple items
val int: value: 'T -> int (requires member op_Explicit)

--------------------
type int = int32

--------------------
type int<'Measure> = int
union case Option.Some: Value: 'T -> Option<'T>
union case Option.None: Option<'T>
val tryGetDomain: email: string -> string option
val email: string
val split: separator: string -> str: string -> string array
<summary> Splits a string by the given separator. &lt;param name="separator"&gt;The delimiter string.&lt;/param&gt; &lt;param name="str"&gt;The string to split.&lt;/param&gt; </summary>
val domain: string
val userDomain: obj
type 'T option = Option<'T>
namespace TDesu.FSharp.ActivePatterns
val describe: input: string -> string
val input: string
module Parse from TDesu.FSharp.ActivePatterns
<summary> Parse active patterns — match and extract parsed values from strings. </summary>
active recognizer Int: string -> int option
<summary> Matches a string that parses as an int32, extracting the value. &lt;param name="str"&gt;The string to parse.&lt;/param&gt; </summary>
val n: int
val sprintf: format: Printf.StringFormat<'T> -> 'T
active recognizer Double: string -> float option
<summary> Matches a string that parses as a double, extracting the value. &lt;param name="str"&gt;The string to parse.&lt;/param&gt; </summary>
val d: float
active recognizer Bool: string -> bool option
<summary> Matches a string that parses as a bool, extracting the value. &lt;param name="str"&gt;The string to parse.&lt;/param&gt; </summary>
val b: bool
active recognizer Guid: string -> Guid option
<summary> Matches a string that parses as a Guid, extracting the value. &lt;param name="str"&gt;The string to parse.&lt;/param&gt; </summary>
val g: Guid
val other: string
val examples: string list
Multiple items
module List from Microsoft.FSharp.Collections

--------------------
type List<'T> = | op_Nil | op_ColonColon of Head: 'T * Tail: 'T list interface IReadOnlyList<'T> interface IReadOnlyCollection<'T> interface IEnumerable interface IEnumerable<'T> member GetReverseIndex: rank: int * offset: int -> int member GetSlice: startIndex: int option * endIndex: int option -> 'T list static member Cons: head: 'T * tail: 'T list -> 'T list member Head: 'T with get member IsEmpty: bool with get member Item: index: int -> 'T with get ...
val map: mapping: ('T -> 'U) -> list: 'T list -> 'U list
val processed: string
val trim: str: string -> string
<summary> Removes leading and trailing whitespace. &lt;param name="str"&gt;The string to trim.&lt;/param&gt; </summary>
val replace: oldValue: string -> newValue: string -> str: string -> string
<summary> Replaces all occurrences of oldValue with newValue. &lt;param name="oldValue"&gt;The substring to find.&lt;/param&gt; &lt;param name="newValue"&gt;The replacement string.&lt;/param&gt; &lt;param name="str"&gt;The input string.&lt;/param&gt; </summary>
val toLowerInv: str: string -> string
<summary> Converts a string to lowercase using invariant culture. &lt;param name="str"&gt;The string to convert.&lt;/param&gt; </summary>
val parts: string
val join: separator: string -> values: string seq -> string
<summary> Joins a sequence of strings with the given separator. &lt;param name="separator"&gt;The delimiter placed between elements.&lt;/param&gt; &lt;param name="values"&gt;The strings to join.&lt;/param&gt; </summary>
val topScores: obj
type ResizeArray<'T> = Collections.Generic.List<'T>
val divide: a: int -> b: int -> int
val b: int
module Guard from TDesu.FSharp
<summary> Guard module — validate-and-throw in one call. </summary>
<remarks> All guards are <c>inline</c> for zero-cost abstraction at call sites. </remarks>
val positive: paramName: string -> value: 'T -> unit (requires comparison and member Zero)
<summary> Throws <see cref="System.ArgumentOutOfRangeException" /> if value is less than or equal to zero. </summary>
<exception cref="System.ArgumentOutOfRangeException">When <paramref name="value" /> &lt;= 0.</exception>
<param name="paramName">Name of the parameter for the exception.</param>
<param name="value">Value that must be positive.</param>
val ignore: value: 'T -> unit
Multiple items
type ArgumentOutOfRangeException = inherit ArgumentException new: unit -> unit + 4 overloads member GetObjectData: info: SerializationInfo * context: StreamingContext -> unit static member ThrowIfEqual<'T> : value: 'T * other: 'T * ?paramName: string -> unit static member ThrowIfGreaterThan<'T (requires 'T :> IComparable<'T>)> : value: 'T * other: 'T * ?paramName: string -> unit static member ThrowIfGreaterThanOrEqual<'T (requires 'T :> IComparable<'T>)> : value: 'T * other: 'T * ?paramName: string -> unit static member ThrowIfLessThan<'T (requires 'T :> IComparable<'T>)> : value: 'T * other: 'T * ?paramName: string -> unit static member ThrowIfLessThanOrEqual<'T (requires 'T :> IComparable<'T>)> : value: 'T * other: 'T * ?paramName: string -> unit static member ThrowIfNegative<'T (requires 'T :> INumberBase<'T>)> : value: 'T * ?paramName: string -> unit static member ThrowIfNegativeOrZero<'T (requires 'T :> INumberBase<'T>)> : value: 'T * ?paramName: string -> unit ...
<summary>The exception that is thrown when the value of an argument is outside the allowable range of values as defined by the invoked method.</summary>

--------------------
ArgumentOutOfRangeException() : ArgumentOutOfRangeException
ArgumentOutOfRangeException(paramName: string) : ArgumentOutOfRangeException
ArgumentOutOfRangeException(message: string, innerException: exn) : ArgumentOutOfRangeException
ArgumentOutOfRangeException(paramName: string, message: string) : ArgumentOutOfRangeException
ArgumentOutOfRangeException(paramName: string, actualValue: obj, message: string) : ArgumentOutOfRangeException
val ex: ArgumentOutOfRangeException
property ArgumentException.ParamName: string with get
<summary>Gets the name of the parameter that causes this exception.</summary>
<returns>The parameter name.</returns>
val processFiles: unit -> unit
val cleanup: IDisposable
val path: string
val pathDispose: obj
val combined: obj
val hash: string
module ContentHash from TDesu.FSharp.Hashing
<summary> Content hashing helpers (SHA256, SHA1, MD5). Netstandard2.1 compatible. </summary>
val sha256Hex: s: string -> string
<summary> SHA256 hash as lowercase hex string. &lt;param name="s"&gt;The string to hash.&lt;/param&gt; </summary>
val data1: byte array
val data2: byte array
val joined: byte array
module Bytes from TDesu.FSharp.Buffers
<namespacedoc><summary>Buffer utilities: Bytes (xor, concat, constantTimeEquals), ArrayPool helpers.</summary></namespacedoc>
val concat2: a: byte array -> b: byte array -> byte array
<summary> Concatenates two byte arrays using BlockCopy (faster than Array.append for bytes). &lt;param name="a"&gt;The first byte array.&lt;/param&gt; &lt;param name="b"&gt;The second byte array.&lt;/param&gt; </summary>
val dictKey: int
module Hash from TDesu.FSharp.Hashing
<namespacedoc><summary>Hashing utilities: ContentHash (SHA256/SHA1/MD5), Hash.combine, CollectionComparer.</summary></namespacedoc>
Pipeline-friendly hash combining using System.HashCode.
val ofArray: xs: 'a array -> int
<summary> Hashes all elements of an array. &lt;param name="xs"&gt;The array of elements to hash.&lt;/param&gt; </summary>
val recentIds: obj
Multiple items
val string: value: 'T -> string

--------------------
type string = String
val hasA: obj
val hasD: obj

Type something to start searching.