p1eXu5.FSharp.ElmishExtensions 1.0.4

dotnet add package p1eXu5.FSharp.ElmishExtensions --version 1.0.4
                    
NuGet\Install-Package p1eXu5.FSharp.ElmishExtensions -Version 1.0.4
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="p1eXu5.FSharp.ElmishExtensions" Version="1.0.4" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="p1eXu5.FSharp.ElmishExtensions" Version="1.0.4" />
                    
Directory.Packages.props
<PackageReference Include="p1eXu5.FSharp.ElmishExtensions" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add p1eXu5.FSharp.ElmishExtensions --version 1.0.4
                    
#r "nuget: p1eXu5.FSharp.ElmishExtensions, 1.0.4"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package p1eXu5.FSharp.ElmishExtensions@1.0.4
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=p1eXu5.FSharp.ElmishExtensions&version=1.0.4
                    
Install as a Cake Addin
#tool nuget:?package=p1eXu5.FSharp.ElmishExtensions&version=1.0.4
                    
Install as a Cake Tool

p1eXu5.FSharp.ElmishExtensions

NuGet

A comprehensive F# library providing helpful utilities and extensions for working with Elmish and F# async workflows. This library includes powerful abstractions for managing asynchronous operations, cancellation token pooling, and deferred computations in WPF and other applications.

Core Types

Cts (Cancellation Token Source Wrapper)

A lightweight wrapper around CancellationTokenSource with pooling support for efficient memory management.

type Cts =
    {
        Token: unit -> CancellationToken
        Cancel: unit -> unit
        Free: unit -> unit
        Dispose: unit -> unit
    }

CtsPool

Manages a reusable pool of CancellationTokenSource instances to reduce allocation overhead in high-frequency async operations.

Operation<'TArg, 'TRes>

Represents a basic operation with start and finish states.

type Operation<'TArg, 'TRes> =
    | Start of 'TArg
    | Finish of 'TRes

AsyncOperation<'Arg, 'Res>

An extension of Operation that tracks the Cts used for cancellation.

type AsyncOperation<'Arg, 'Res> =
    | Start of 'Arg
    | Finish of 'Res * operationId: Cts

Deferred<'Retrieved>

Represents the state of a deferred computation without cancellation support.

type Deferred<'Retrieved> =
    | NotRequested
    | InProgress
    | Retrieved of 'Retrieved

AsyncDeferred<'Retrieved>

A deferred computation with cancellation support through Cts.

type AsyncDeferred<'Retrieved> =
    | NotRequested
    | InProgress of Cts
    | Retrieved of 'Retrieved

PreparingDeferred<'Preparing, 'Retrieved>

A deferred computation that tracks a preparing/initializing state and the final retrieved value.

type PreparingDeferred<'Preparing, 'Retrieved> =
    | Preparing of 'Preparing
    | InProgress of 'Preparing
    | Retrieved of 'Retrieved

AsyncPreparingDeferred<'Preparing, 'Retrieved>

Similar to PreparingDeferred but with cancellation support.

type AsyncPreparingDeferred<'Preparing, 'Retrieved> =
    | Preparing of 'Preparing
    | InProgress of 'Preparing * Cts
    | Retrieved of 'Retrieved

AsyncDeferredState & AsyncPreparingDeferredState

State-only variants of AsyncDeferred and AsyncPreparingDeferred that don't carry the retrieved value (useful when the value is stored elsewhere).

type AsyncDeferredState =
    | NotRequested
    | InProgress of Cts
    | Retrieved

type AsyncPreparingDeferredState<'Preparing> =
    | Preparing of 'Preparing
    | InProgress of 'Preparing * Cts
    | Retrieved

Helper Functions

AsyncOperation module

Basic helper functions for constructing and working with AsyncOperation messages.

// Creates a Start message with arguments
AsyncOperation.start opMsgCtor args

// Creates a Start message with unit argument
AsyncOperation.startUnit opMsgCtor

// Creates a Finish constructor from a Cts
AsyncOperation.finish cts

// Creates a Finish message from a Cts
AsyncOperation.finishWithin msgCtor cts

AsyncDeferred module

Functions for managing async deferred values and cancellation.

// Cancels in-progress operation and starts a new one
// Returns None if already retrieved
AsyncDeferred.tryInProgressWithCancellation asyncDeferred

// Force starts a new in-progress operation, canceling any current one
AsyncDeferred.forceInProgressWithCancellation asyncDeferred

// Safely completes a deferred operation if Cts matches
AsyncDeferred.chooseRetrievedWithin retrievedValue cts asyncDeferred

// Safely completes with a Result type
AsyncDeferred.chooseRetrievedResultWithin asyncOperationResult cts asyncDeferred

// Extract retrieved value as option
AsyncDeferred.chooseRetrieved asyncDeferred

// Cancel and reset to NotRequested
AsyncDeferred.notRequestedWithCancellation asyncDeferred

// Force to Retrieved state
AsyncDeferred.forceRetrievedWithCancellation retrievedValue asyncDeferred

// Active pattern for safe Cts disposal and validation
AsyncDeferred.(|InProgressWithCts|_|) opCts asyncDeferred

// Extract value with exception if not retrieved
AsyncDeferred.retrievedValue asyncDeferred

// Convert to option
AsyncDeferred.toOption asyncDeferred

// Functor map
AsyncDeferred.map f asyncDeferred

// Map with model update pattern (returns value and Cmd)
AsyncDeferred.mapUpdate f asyncDeferred

Model module

Functional utilities for working with model fields.

// Map over a model field using getter and setter
Model.map get set f model

List module

Utilities for updating specific elements in lists.

// Update first element matching predicate
List.mapFirst predicate updatef modelList

// Update first element with Cmd result
List.mapFirstCmd predicate updatef modelList

// Update first element with Cmd and Intent
List.mapFirstCmdIntent predicate updatef defaultIntent modelList

// Update first element with Intent
List.mapFirstIntent predicate updatef defaultIntent modelList

Helpers module

Simple utility functions.

// Return model with Cmd.none
withCmdNone model

// Flip argument order for a function
flip f b a  // equivalent to f a b

Examples

AsyncDeferred State Management

type StatisticListModel =
    {
        StatisticList: AsyncDeferred<StatisticModel list>
        StartDate: DateOnly
        EndDate: DateOnly
    }

module StatisticListModel =
    let period (model: StatisticListModel) =
        (model.StartDate, model.EndDate) ||> DateOnlyPeriod.create

     let withStatisticList deff (model: StatisticListModel) =
        { model with StatisticList = deff }

type Msg =
    | LoadStatisticList of AsyncOperation<unit, Result<DailyStatistic list, string>>

module MsgWith =

    let (|``Start of LoadStatisticList``|_|) (model: StatisticListModel) (msg: Msg) =
        match msg with
        | Msg.LoadStatisticList (AsyncOperation.Start _) ->
            model.StatisticList |> AsyncDeferred.forceInProgressWithCancellation |> Some
        | _ -> None

    let (|``Finish of LoadStatisticList``|_|) (model: StatisticListModel) (msg: Msg) =
        match msg with
        | Msg.LoadStatisticList (AsyncOperation.Finish (res, cts)) ->
            model.StatisticList
            |> AsyncDeferred.chooseRetrievedResultWithin res cts
            |> Option.map (
                Result.map (fun (_, res) ->
                    res
                    |> List.map StatisticModel.init
                    |> AsyncDeferred.Retrieved
                )
            )
        | _ -> None

module Program =

    let update eventStore errorMessageQueue msg model =
        match msg with
        | MsgWith.``Start of LoadStatisticList`` model (deff, cts) ->
            let period = model |> period

            model |> withStatisticList deff
            , Cmd.OfTask.perform
                eventStore.ProjectStatisticList
                (period, cts.Token)
                (AsyncOperation.finishWithin Msg.LoadStatisticList cts)
            , Intent.None

        | MsgWith.``Finish of LoadStatisticList`` model res ->
            match res with
            | Ok deff ->
                model |> withStatisticList deff
                , Cmd.none
                , Intent.None
            | Error err ->
                do errorMessageQueue.EnqueueError err
                logger.LogError(err)
                model |> withStatisticList AsyncDeferred.NotRequested
                , Cmd.none
                , Intent.None

module Bindings =

    let bindings () =
        [
            LoadStatisticListCommand
                |> Binding.cmd (AsyncOperation.startUnit Msg.LoadStatisticList)
        ]
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.4 90 5/15/2026
1.0.3 96 5/1/2026
1.0.2 101 5/1/2026
1.0.1 96 4/26/2026
1.0.0 59 4/18/2026
0.0.1 227 6/2/2025

ENHANCEMENT: Adds List bindings - tryMapFirst, tryMapFirstCmd, tryMapFirstCmdIntent, mapFirstIntentf, tryMapFirstIntent