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
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. <param name="error">The error value to use when the value is null.</param> <param name="value">The value to check for null.</param> </summary>
<summary> Returns Ok(value) if not null, Error(error) if null. <param name="error">The error value to use when the value is null.</param> <param name="value">The value to check for null.</param> </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. <param name="f">The function returning a new Result.</param> <param name="r">The result to bind over.</param> </summary>
--------------------
val bind: binder: ('T -> Result<'U,'TError>) -> result: Result<'T,'TError> -> Result<'U,'TError>
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. <param name="f">The function returning a new Result.</param> <param name="r">The result to bind over.</param> </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
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. <param name="f">The mapping function to apply to the Ok value.</param> <param name="r">The result to transform.</param> </summary>
--------------------
val map: mapping: ('T -> 'U) -> result: Result<'T,'TError> -> Result<'U,'TError>
val map: [<InlineIfLambda>] f: ('a -> 'b) -> r: Result<'a,'c> -> Result<'b,'c>
<summary> Transforms the Ok value with f, passing Error through unchanged. <param name="f">The mapping function to apply to the Ok value.</param> <param name="r">The result to transform.</param> </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. <param name="f">The side-effect function to apply on Ok.</param> <param name="r">The result to inspect.</param> </summary>
<summary> Applies a side-effect on Ok and returns the result unchanged. <param name="f">The side-effect function to apply on Ok.</param> <param name="r">The result to inspect.</param> </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. <param name="f">The side-effect function to apply on Error.</param> <param name="r">The result to inspect.</param> </summary>
<summary> Applies a side-effect on Error and returns the result unchanged. <param name="f">The side-effect function to apply on Error.</param> <param name="r">The result to inspect.</param> </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
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. <param name="separator">The delimiter string.</param> <param name="str">The string to split.</param> </summary>
<summary> Splits a string by the given separator. <param name="separator">The delimiter string.</param> <param name="str">The string to split.</param> </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>
<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. <param name="str">The string to parse.</param> </summary>
<summary> Matches a string that parses as an int32, extracting the value. <param name="str">The string to parse.</param> </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. <param name="str">The string to parse.</param> </summary>
<summary> Matches a string that parses as a double, extracting the value. <param name="str">The string to parse.</param> </summary>
val d: float
active recognizer Bool: string -> bool option
<summary> Matches a string that parses as a bool, extracting the value. <param name="str">The string to parse.</param> </summary>
<summary> Matches a string that parses as a bool, extracting the value. <param name="str">The string to parse.</param> </summary>
val b: bool
active recognizer Guid: string -> Guid option
<summary> Matches a string that parses as a Guid, extracting the value. <param name="str">The string to parse.</param> </summary>
<summary> Matches a string that parses as a Guid, extracting the value. <param name="str">The string to parse.</param> </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 ...
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. <param name="str">The string to trim.</param> </summary>
<summary> Removes leading and trailing whitespace. <param name="str">The string to trim.</param> </summary>
val replace: oldValue: string -> newValue: string -> str: string -> string
<summary> Replaces all occurrences of oldValue with newValue. <param name="oldValue">The substring to find.</param> <param name="newValue">The replacement string.</param> <param name="str">The input string.</param> </summary>
<summary> Replaces all occurrences of oldValue with newValue. <param name="oldValue">The substring to find.</param> <param name="newValue">The replacement string.</param> <param name="str">The input string.</param> </summary>
val toLowerInv: str: string -> string
<summary> Converts a string to lowercase using invariant culture. <param name="str">The string to convert.</param> </summary>
<summary> Converts a string to lowercase using invariant culture. <param name="str">The string to convert.</param> </summary>
val parts: string
val join: separator: string -> values: string seq -> string
<summary> Joins a sequence of strings with the given separator. <param name="separator">The delimiter placed between elements.</param> <param name="values">The strings to join.</param> </summary>
<summary> Joins a sequence of strings with the given separator. <param name="separator">The delimiter placed between elements.</param> <param name="values">The strings to join.</param> </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>
<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" /> <= 0.</exception>
<param name="paramName">Name of the parameter for the exception.</param>
<param name="value">Value that must be positive.</param>
<summary> Throws <see cref="System.ArgumentOutOfRangeException" /> if value is less than or equal to zero. </summary>
<exception cref="System.ArgumentOutOfRangeException">When <paramref name="value" /> <= 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
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>
<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>
<summary> Content hashing helpers (SHA256, SHA1, MD5). Netstandard2.1 compatible. </summary>
val sha256Hex: s: string -> string
<summary> SHA256 hash as lowercase hex string. <param name="s">The string to hash.</param> </summary>
<summary> SHA256 hash as lowercase hex string. <param name="s">The string to hash.</param> </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>
<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). <param name="a">The first byte array.</param> <param name="b">The second byte array.</param> </summary>
<summary> Concatenates two byte arrays using BlockCopy (faster than Array.append for bytes). <param name="a">The first byte array.</param> <param name="b">The second byte array.</param> </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.
<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. <param name="xs">The array of elements to hash.</param> </summary>
<summary> Hashes all elements of an array. <param name="xs">The array of elements to hash.</param> </summary>
val recentIds: obj
Multiple items
val string: value: 'T -> string
--------------------
type string = String
val string: value: 'T -> string
--------------------
type string = String
val hasA: obj
val hasD: obj
TDesu.FSharp