Orsak 0.5.0

There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package Orsak --version 0.5.0
                    
NuGet\Install-Package Orsak -Version 0.5.0
                    
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="Orsak" Version="0.5.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Orsak" Version="0.5.0" />
                    
Directory.Packages.props
<PackageReference Include="Orsak" />
                    
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 Orsak --version 0.5.0
                    
#r "nuget: Orsak, 0.5.0"
                    
#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 Orsak@0.5.0
                    
#: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=Orsak&version=0.5.0
                    
Install as a Cake Addin
#tool nuget:?package=Orsak&version=0.5.0
                    
Install as a Cake Tool

Orsak


eff {
    let! line = Effects.Console.readLine()
    do! Effect.Console.writeLine $"Hello {line}"
}

Orsak is a library for function effects in F#, allowing pragmatic and composable modelling of side-effects through interfaces. It is inspired by Zio, with F# encoding similar to the approach described by Bartosz Sypytkowski here. The library intends to be as complete as is practical, including a computation expression, supporting functions and operators, and should be compatible with FSharpPlus.

However, Orsak is not intended to be a framework. Rather, it is encouraged and recommended to make use of the existing .NET ecosystem, and Orsak is intended to make that as easy and friction-free as possible. It can be used piecemeal, and introduced to existing codebases in isolated chunks.


This implementation makes use of resumable code to implement the computation expression builder for the lowest possible overhead. The builder also has various overloads for Bind, allowing for friction free interop with TaskLike<'a>, Async<'a>, Result<'T,'E> and more. It supports for, while, use, try-with and try-finally, and also applicative bind when the error-type supports +. While the computation expression is the intended way of working with effects, the corresponding module should contain all the expected functions.

NuGet Badge Build & Tests

Show me the code


Imagine having the following interfaces, which each describes some none-pure operation, that is, they both have side-effects.

type IButtonPusher =
    abstract member PushButton: unit -> Task<unit>
    
type IBeanCounter =
    abstract member CountBeans: unit -> Task<int>

By creating the following helper-interfaces

type IButtonPusherProvider =
    abstract member ButtonPusher: IButtonPusher
    
type IBeanCounterProvider =
    abstract member BeanCounter: IBeanCounter

and the following helpers

let pushButton () =
    Effect.Create(fun (provider: #IButtonPusherProvider) -> provider.ButtonPusher.PushButton())
    
let countBeans () =
    Effect.Create(fun (provider: #IBeanCounterProvider) -> provider.BeanCounter.CountBeans())

then it is possible to partially apply, or 'inject' these interfaces into your code by simply making functions calls:

let pushAndCount<'a, 'b when 'a :> IButtonPusherProvider and 'a :> IBeanCounterProvider> ()
    : Effect<'a, int, 'b> =
    eff {
        do! pushButton ()
        let! beans = countBeans ()
        return beans * 2
    }

In essence, this is a partially applied function, waiting for an instance of 'a which implements both IButtonPusherProvider and IBeanCounterProvider. Now, in practise you do not need to specify any of this, the type inference will keep track of the requirements of your provider.

let pushAndCount () =
    eff {
        do! pushButton()
        let! beans = countBeans()
        return beans * 2
    }

And adding further calls to functions with side-effects will apply the correct constraints seamlessly.


Main documentation is available at https://johsand.github.io/Orsak/

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  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 was computed.  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 was computed.  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 (1)

Showing the top 1 NuGet packages that depend on Orsak:

Package Downloads
Orsak.AspNetCore

Package Description

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.5.1-beta0029 297 11/13/2025
0.5.1-beta0028 638 4/21/2025
0.5.1-beta0024 243 4/20/2025
0.5.1-beta0009 228 4/20/2025
0.5.1-beta0008 164 4/19/2025
0.5.1-beta0002 169 4/19/2025
0.5.0 1,969 4/19/2025
0.4.3-beta0036 263 4/16/2025
0.4.3-beta0033 150 4/5/2025
0.4.3-beta0031 161 4/5/2025
0.4.3-beta0022 202 6/5/2024
0.4.3-beta0016 177 3/8/2024
0.4.3-beta0015 230 1/11/2024
0.4.3-beta0014 188 1/11/2024
0.4.3-beta0013 160 1/11/2024
0.4.3-beta0011 169 1/11/2024
0.4.3-beta0007 221 11/20/2023
0.4.3-beta0004 168 11/20/2023
0.4.3-beta0003 156 11/20/2023
0.4.2 18,363 11/1/2023
0.4.2-beta0008 134 11/1/2023
0.4.1 1,342 10/19/2023
0.4.1-beta0002 159 10/5/2023
0.4.1-beta0001 174 9/29/2023
0.4.0 954 9/19/2023
0.3.1-beta0015 187 9/19/2023
0.3.1-beta0014 178 9/17/2023
0.3.1-beta0013 173 9/17/2023
0.3.1-beta0011 231 5/1/2023
0.3.1-beta0010 266 4/25/2023
0.3.1-beta0009 263 4/24/2023
0.3.1-beta0008 222 4/24/2023
0.3.1-beta0007 250 4/24/2023
0.3.1-beta0005 268 4/22/2023
0.3.1-beta0002 250 4/15/2023
0.3.1-beta0001 242 4/16/2023
0.3.0 2,123 4/15/2023
0.2.1-beta0009 272 4/15/2023
0.2.1-beta0008 226 4/15/2023
0.2.1-beta0006 263 4/13/2023
0.2.1-beta0005 243 4/12/2023
0.2.1-beta0004 262 4/12/2023
0.2.1-beta0002 244 4/11/2023
0.2.1-beta0001 244 4/9/2023
0.2.0 331 4/6/2023
0.1.1-beta0006 267 4/6/2023
0.1.1-beta0004 267 4/6/2023
0.1.1-beta0001 241 4/2/2023
0.1.0 342 3/27/2023
0.1.0-beta0049 246 3/27/2023
0.1.0-beta0047 275 3/25/2023
0.1.0-beta0046 260 3/25/2023
0.1.0-beta0029 266 3/27/2023