Fletched.Core
0.1.0
dotnet add package Fletched.Core --version 0.1.0
NuGet\Install-Package Fletched.Core -Version 0.1.0
<PackageReference Include="Fletched.Core" Version="0.1.0" />
<PackageVersion Include="Fletched.Core" Version="0.1.0" />
<PackageReference Include="Fletched.Core" />
paket add Fletched.Core --version 0.1.0
#r "nuget: Fletched.Core, 0.1.0"
#:package Fletched.Core@0.1.0
#addin nuget:?package=Fletched.Core&version=0.1.0
#tool nuget:?package=Fletched.Core&version=0.1.0
Fletched
A Typed Relational Engine for .NET
This project implements a high-performance relational logic engine embedded directly into C#. It draws inspiration from Prolog and microKanren, but deliberately departs from traditional designs to leverage modern .NET capabilities such as source generation, strong typing, and JIT optimization.
The goal is not to recreate a standalone Prolog system, but to provide a focused, composable logic layer that integrates seamlessly with existing .NET applications.
Core Concepts
Embedded DSL via Source Generators
Predicates and facts are defined using standard C# constructs and attributes. A source generator rewrites these definitions into optimized execution code at compile time.
[Fact]
partial record struct User(string Login, string Name);
[Predicate]
partial record struct AdminUsers
{
[PredicateBody]
LogicExpr<bool> Body(TerminalVar<string> name) =>
With<User, Admin>((user, admin) =>
user.Name == name &&
user.Login == admin.Login
);
}
This code looks like regular C#, but is interpreted as a typed logical expression.
Strongly Typed Logical Model
The system uses a typed DSL based on:
- "LogicExpr<T>" — symbolic expressions
- "TerminalVar<T>" — query boundaries
- generated proxies for facts — enabling typed field access
Operators such as "==" and "&&" are reinterpreted as:
- unification
- logical conjunction
This allows compile-time validation while preserving a natural syntax.
Compiled Execution (No Interpreter)
Instead of interpreting logic at runtime, the system:
- Builds a typed intermediate representation (IR)
- Compiles it into specialized C# code
- Executes it using an efficient, imperative runtime
Key characteristics:
- No reflection at runtime
- No expression tree interpretation
- Fully inlined execution paths
- JIT-optimized code
Execution Model
The engine combines:
- microKanren-style semantics (pure logical model)
- WAM-inspired optimizations (efficient execution)
Core runtime features include:
- slot-based variable storage (compiled to typed fields)
- backtracking via choice points
- trail-based state restoration
- synchronous result enumeration (
IEnumerable<T>viaExecute, goto-based iterator) - native async result enumeration (
IAsyncEnumerable<T>viaExecuteAsync, switch-loop state machine) withCancellationTokensupport
Fact Storage and Querying
Facts are stored in strongly typed tables:
FactTable<User>
Queries are compiled into efficient loops and joins over these tables, with optional indexing for performance.
List ergonomics
Logical lists support concise DSL and runtime construction:
[Fact]
partial record struct NumberSequence(string Name, LogicList<int> Numbers);
[Predicate]
partial record struct PairSequence
{
[PredicateBody]
public static LogicExpr<bool> Body(TerminalVar<string> name) =>
Logic.With<NumberSequence>(ns =>
ns.Name == name &&
ns.Numbers == Logic.List(1, 2)
);
}
var facts = new[]
{
new NumberSequence("empty", LogicList<int>.Create()),
new NumberSequence("pair", LogicList<int>.Create(1, 2)),
};
Predicate Composition
Predicates can call other predicates and participate in backtracking. Calls are compiled into state machines or inlined logic, enabling:
- composability
- reuse
- efficient multi-solution enumeration
Predicates may also declare multiple [PredicateBody] methods on the same record as long as each body has a distinct arity.
[Predicate]
partial record struct PersonLookup
{
[PredicateBody]
public static LogicExpr<bool> Body(TerminalVar<string> name) =>
Logic.With<Person>(person => person.Name == name);
[PredicateBody]
public static LogicExpr<bool> Body(TerminalVar<string> login, TerminalVar<string> name) =>
Logic.With<Person>(person =>
person.Login == login &&
person.Name == name);
}
Single-body predicates keep the existing Execute(...) / *Result surface. Overloaded predicates generate arity-specific entry points such as ExecuteArity1(...), ExecuteArity2(...), and matching result types.
Design Goals
- Performance-first: generated code rivals hand-written imperative logic
- Type safety: full integration with the C# type system
- Minimal runtime overhead: no interpreter, no dynamic dispatch
- Composable logic: small, reusable predicates
- .NET interop: seamless integration with existing code
Samples
The repository includes runnable samples under samples/.
The first sample is samples/WorkAssignment, a console application that models a
7-day schedule with early/late shifts, worker availability constraints, and fair
assignment search expressed in the Fletched DSL.
See Samples.md for an overview of the sample and the exact commands to run it with generated input or CSV input. For a ready-to-use GitHub Codespaces and VS Code setup, see Codespace.md. For NuGet packaging and publishing guidance, see Nuget.md.
Non-Goals
- Full ISO Prolog compatibility
- Dynamic runtime evaluation of arbitrary code
- General-purpose programming language replacement
Summary
This project explores a different point in the design space:
A compiled, strongly typed relational DSL for .NET, combining the clarity of logic programming with the performance characteristics of generated imperative code.
More detailed design documents (IR, execution model, trade-offs) are available in the repository under specs/.
Name origin - Claude
https://claude.ai/share/ef4597bd-40dc-475f-9dff-42bd052d49b7
From Zeno to fletched – from the "arrow paradox" (a fletched arrow)
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. 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 was computed. 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 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. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- No dependencies.
-
net10.0
- No dependencies.
-
net6.0
- No dependencies.
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Fletched.Core:
| Package | Downloads |
|---|---|
|
Fletched.Roslyn
Roslyn source generator for the Fletched typed relational engine. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.1.0 | 139 | 5/10/2026 |