FPropose 1.2.0

dotnet add package FPropose --version 1.2.0
                    
NuGet\Install-Package FPropose -Version 1.2.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="FPropose" Version="1.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="FPropose" Version="1.2.0" />
                    
Directory.Packages.props
<PackageReference Include="FPropose" />
                    
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 FPropose --version 1.2.0
                    
#r "nuget: FPropose, 1.2.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 FPropose@1.2.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=FPropose&version=1.2.0
                    
Install as a Cake Addin
#tool nuget:?package=FPropose&version=1.2.0
                    
Install as a Cake Tool

FPropose

Composable predicates for F# that return a boolean and explain why that result holds for a specific value. Explanations can follow normal short-circuiting (Lazy) or evaluate every sub-predicate for auditing (Eager).

Install

dotnet add package FPropose

Quick example

open FPropose
open FPropose.Operators

let canVote =
    Pred.leafMsg "age" (fun p -> p.Age >= 18)
        (fun _ -> "Meets minimum age.")
        (fun p -> $"Age {p.Age} is below 18.")

let registered =
    Pred.leafMsg "registered" (fun p -> p.Registered)
        (fun _ -> "Account is registered.")
        (fun _ -> "Account is not registered.")

let p = canVote .&&. registered
let person = {| Name = "Ada"; Age = 17; Registered = false |}

if Pred.eval p person then
    printfn "OK"
else
    printfn "%s" (Pred.explainText ExplainMode.Lazy p person)

ExplainTree captures structure; call .Format() or ExplainTree.format for plain text.

API overview

Construct Use
Pred.leaf name test explain Atomic test; explain receives the value and the pass/fail flag.
Pred.leaf' test explain Same as leaf, without a separate display name (detail only in formatted output).
Pred.leafMsg name test onTrue onFalse Convenience when messages differ only by outcome.
Pred.leafMsg' test onTrue onFalse Same as leafMsg, without a separate display name.
Pred.conj / Pred.disj / Pred.neg AND, OR, NOT.
Pred.all / Pred.any Fold over lists (all [] is always true; any [] always false).
Pred.forAll name getItems inner Every element from getItems must satisfy inner; nested explanations per item (empty sequence is vacuously true).
Pred.forAll' getItems inner Same as forAll, without a separate quantifier label in formatted output.
Pred.exists name getItems inner At least one element from getItems must satisfy inner; nested explanations per item (empty sequence is vacuously false).
Pred.exists' getItems inner Same as exists, without a separate quantifier label in formatted output.
Pred.contramap Focus a predicate on part of a larger value.
Pred.eval Boolean result with standard short-circuiting for AND and OR.
Pred.explain PropositionResult using lazy explanation.
Pred.explainWith ExplainMode.Eager Full sub-tree regardless of short-circuit.
Pred.explainText Same as explain, rendered as a string.
FPropose.Operators .&&., .\|\|., ~~~

Developing locally

Prerequisites: .NET 8 SDK.

git clone https://github.com/icalvo/FPropose.git
cd FPropose
dotnet restore
dotnet build
dotnet test

Open as a workspace

In Cursor or VS Code, use File → Open Folder and select the FPropose directory (the folder that contains FPropose.sln).

Repository

Source lives at github.com/icalvo/FPropose. If you cloned without a remote:

git remote add origin https://github.com/icalvo/FPropose.git
git push -u origin master

Project layout

  • CHANGELOG.md — release history (Keep a Changelog)
  • src/FPropose — library (Explain.fs, Pred.fs)
  • tests/FPropose.Tests — xUnit tests

Agent releases: load the deploy-release skill (.cursor/skills/deploy-release/SKILL.md) for changelog → tag → GitHub Release → NuGet publish.

Packaging locally

dotnet pack src/FPropose/FPropose.fsproj -c Release -o ./artifacts -p:PackageVersion=0.1.0-local

Outputs .nupkg (and symbols) under ./artifacts.

Publishing to NuGet.org (CI)

One-time setup

  1. Use this repository (icalvo/FPropose); Directory.Build.props and this README already point at it.
  2. Create an API key on NuGet.org with Push scope for package id FPropose.
  3. In the GitHub repo, add a secret named NUGET_API_KEY containing that key (Settings → Secrets and variables → Actions).

Publish when you cut a GitHub Release

  1. Update Version / release notes as needed.
  2. Create a Release in GitHub and publish it. Use a tag like v0.2.0 (the workflow strips a leading v for the package version).
  3. The Publish to NuGet workflow packs FPropose and runs dotnet nuget push to https://api.nuget.org/v3/index.json.

Publish manually from Actions

  1. Go to Actions → Publish to NuGet → Run workflow.
  2. Enter a SemVer version (e.g. 0.2.0).

After the first publish

Confirm the package appears on NuGet Gallery. If the id is taken, change <PackageId> in src/FPropose/FPropose.fsproj and the secret scope to match.

License

MIT — see LICENSE.

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 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

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.2.0 65 5/17/2026
1.1.0 94 5/8/2026
1.0.0 84 5/7/2026
0.1.0 89 5/7/2026