Skip to content

Commit bca87e0

Browse files
Daniel LarsenCopilot
andauthored
Improved net lib, refactored project structure, added XML documentation (#34)
* Improved NET library * Comments + structure changes * Update NuGet * Update src/FSharp.FIO/DSL/Core.fs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 80e8c42 commit bca87e0

File tree

27 files changed

+2589
-630
lines changed

27 files changed

+2589
-630
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,3 +457,7 @@ Scripts/
457457
/benchmarks/FSharp.FIO.Benchmarks/results
458458
/benchmarks/FSharp.FIO.Benchmarks.Plots/boxplot_data
459459
/benchmarks/FSharp.FIO.Benchmarks.Plots/lineplot_data
460+
461+
### Cursor ###
462+
.cursor/rules/cursor-rule.mdc
463+
.cursor/rules/fio-cursor-rule.mdc

FSharp.FIO.sln

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ VisualStudioVersion = 17.0.32014.148
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.FIO", "src\FSharp.FIO\FSharp.FIO.fsproj", "{0B1D12CA-CD2E-4BEB-84F3-6549878A7DC8}"
77
EndProject
8+
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.FIO.Lib", "src\FSharp.FIO.Lib\FSharp.FIO.Lib.fsproj", "{C9B34D89-0818-4A9E-B9CB-73F44AAC3CAE}"
9+
EndProject
10+
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.FIO.App", "src\FSharp.FIO.App\FSharp.FIO.App.fsproj", "{9B9EE2E5-E6C8-47A8-B610-8C7454B63969}"
11+
EndProject
812
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.FIO.Examples", "examples\FSharp.FIO.Examples\FSharp.FIO.Examples.fsproj", "{543F6D16-0C1D-42ED-815F-255E3AAB713C}"
913
EndProject
1014
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.FIO.Examples.App", "examples\FSharp.FIO.Examples.App\FSharp.FIO.Examples.App.fsproj", "{99438A99-5068-4642-BAD6-6D8C8DD16412}"
@@ -37,6 +41,18 @@ Global
3741
{0B1D12CA-CD2E-4BEB-84F3-6549878A7DC8}.Release|x64.Build.0 = Release|Any CPU
3842
{0B1D12CA-CD2E-4BEB-84F3-6549878A7DC8}.Release|x86.ActiveCfg = Release|Any CPU
3943
{0B1D12CA-CD2E-4BEB-84F3-6549878A7DC8}.Release|x86.Build.0 = Release|Any CPU
44+
{C9B34D89-0818-4A9E-B9CB-73F44AAC3CAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
45+
{C9B34D89-0818-4A9E-B9CB-73F44AAC3CAE}.Debug|Any CPU.Build.0 = Debug|Any CPU
46+
{C9B34D89-0818-4A9E-B9CB-73F44AAC3CAE}.Debug|x64.ActiveCfg = Debug|Any CPU
47+
{C9B34D89-0818-4A9E-B9CB-73F44AAC3CAE}.Debug|x64.Build.0 = Debug|Any CPU
48+
{C9B34D89-0818-4A9E-B9CB-73F44AAC3CAE}.Debug|x86.ActiveCfg = Debug|Any CPU
49+
{C9B34D89-0818-4A9E-B9CB-73F44AAC3CAE}.Debug|x86.Build.0 = Debug|Any CPU
50+
{C9B34D89-0818-4A9E-B9CB-73F44AAC3CAE}.Release|Any CPU.ActiveCfg = Release|Any CPU
51+
{C9B34D89-0818-4A9E-B9CB-73F44AAC3CAE}.Release|Any CPU.Build.0 = Release|Any CPU
52+
{C9B34D89-0818-4A9E-B9CB-73F44AAC3CAE}.Release|x64.ActiveCfg = Release|Any CPU
53+
{C9B34D89-0818-4A9E-B9CB-73F44AAC3CAE}.Release|x64.Build.0 = Release|Any CPU
54+
{C9B34D89-0818-4A9E-B9CB-73F44AAC3CAE}.Release|x86.ActiveCfg = Release|Any CPU
55+
{C9B34D89-0818-4A9E-B9CB-73F44AAC3CAE}.Release|x86.Build.0 = Release|Any CPU
4056
{543F6D16-0C1D-42ED-815F-255E3AAB713C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
4157
{543F6D16-0C1D-42ED-815F-255E3AAB713C}.Debug|Any CPU.Build.0 = Debug|Any CPU
4258
{543F6D16-0C1D-42ED-815F-255E3AAB713C}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -49,6 +65,18 @@ Global
4965
{543F6D16-0C1D-42ED-815F-255E3AAB713C}.Release|x64.Build.0 = Release|Any CPU
5066
{543F6D16-0C1D-42ED-815F-255E3AAB713C}.Release|x86.ActiveCfg = Release|Any CPU
5167
{543F6D16-0C1D-42ED-815F-255E3AAB713C}.Release|x86.Build.0 = Release|Any CPU
68+
{99438A99-5068-4642-BAD6-6D8C8DD16412}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
69+
{99438A99-5068-4642-BAD6-6D8C8DD16412}.Debug|Any CPU.Build.0 = Debug|Any CPU
70+
{99438A99-5068-4642-BAD6-6D8C8DD16412}.Debug|x64.ActiveCfg = Debug|Any CPU
71+
{99438A99-5068-4642-BAD6-6D8C8DD16412}.Debug|x64.Build.0 = Debug|Any CPU
72+
{99438A99-5068-4642-BAD6-6D8C8DD16412}.Debug|x86.ActiveCfg = Debug|Any CPU
73+
{99438A99-5068-4642-BAD6-6D8C8DD16412}.Debug|x86.Build.0 = Debug|Any CPU
74+
{99438A99-5068-4642-BAD6-6D8C8DD16412}.Release|Any CPU.ActiveCfg = Release|Any CPU
75+
{99438A99-5068-4642-BAD6-6D8C8DD16412}.Release|Any CPU.Build.0 = Release|Any CPU
76+
{99438A99-5068-4642-BAD6-6D8C8DD16412}.Release|x64.ActiveCfg = Release|Any CPU
77+
{99438A99-5068-4642-BAD6-6D8C8DD16412}.Release|x64.Build.0 = Release|Any CPU
78+
{99438A99-5068-4642-BAD6-6D8C8DD16412}.Release|x86.ActiveCfg = Release|Any CPU
79+
{99438A99-5068-4642-BAD6-6D8C8DD16412}.Release|x86.Build.0 = Release|Any CPU
5280
{FF020285-6B80-4420-93A3-5B62B65D3C22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
5381
{FF020285-6B80-4420-93A3-5B62B65D3C22}.Debug|Any CPU.Build.0 = Debug|Any CPU
5482
{FF020285-6B80-4420-93A3-5B62B65D3C22}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -85,18 +113,18 @@ Global
85113
{C268093D-D055-4DDF-BD0D-B9499E92CED1}.Release|x64.Build.0 = Release|Any CPU
86114
{C268093D-D055-4DDF-BD0D-B9499E92CED1}.Release|x86.ActiveCfg = Release|Any CPU
87115
{C268093D-D055-4DDF-BD0D-B9499E92CED1}.Release|x86.Build.0 = Release|Any CPU
88-
{99438A99-5068-4642-BAD6-6D8C8DD16412}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
89-
{99438A99-5068-4642-BAD6-6D8C8DD16412}.Debug|Any CPU.Build.0 = Debug|Any CPU
90-
{99438A99-5068-4642-BAD6-6D8C8DD16412}.Debug|x64.ActiveCfg = Debug|Any CPU
91-
{99438A99-5068-4642-BAD6-6D8C8DD16412}.Debug|x64.Build.0 = Debug|Any CPU
92-
{99438A99-5068-4642-BAD6-6D8C8DD16412}.Debug|x86.ActiveCfg = Debug|Any CPU
93-
{99438A99-5068-4642-BAD6-6D8C8DD16412}.Debug|x86.Build.0 = Debug|Any CPU
94-
{99438A99-5068-4642-BAD6-6D8C8DD16412}.Release|Any CPU.ActiveCfg = Release|Any CPU
95-
{99438A99-5068-4642-BAD6-6D8C8DD16412}.Release|Any CPU.Build.0 = Release|Any CPU
96-
{99438A99-5068-4642-BAD6-6D8C8DD16412}.Release|x64.ActiveCfg = Release|Any CPU
97-
{99438A99-5068-4642-BAD6-6D8C8DD16412}.Release|x64.Build.0 = Release|Any CPU
98-
{99438A99-5068-4642-BAD6-6D8C8DD16412}.Release|x86.ActiveCfg = Release|Any CPU
99-
{99438A99-5068-4642-BAD6-6D8C8DD16412}.Release|x86.Build.0 = Release|Any CPU
116+
{9B9EE2E5-E6C8-47A8-B610-8C7454B63969}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
117+
{9B9EE2E5-E6C8-47A8-B610-8C7454B63969}.Debug|Any CPU.Build.0 = Debug|Any CPU
118+
{9B9EE2E5-E6C8-47A8-B610-8C7454B63969}.Debug|x64.ActiveCfg = Debug|Any CPU
119+
{9B9EE2E5-E6C8-47A8-B610-8C7454B63969}.Debug|x64.Build.0 = Debug|Any CPU
120+
{9B9EE2E5-E6C8-47A8-B610-8C7454B63969}.Debug|x86.ActiveCfg = Debug|Any CPU
121+
{9B9EE2E5-E6C8-47A8-B610-8C7454B63969}.Debug|x86.Build.0 = Debug|Any CPU
122+
{9B9EE2E5-E6C8-47A8-B610-8C7454B63969}.Release|Any CPU.ActiveCfg = Release|Any CPU
123+
{9B9EE2E5-E6C8-47A8-B610-8C7454B63969}.Release|Any CPU.Build.0 = Release|Any CPU
124+
{9B9EE2E5-E6C8-47A8-B610-8C7454B63969}.Release|x64.ActiveCfg = Release|Any CPU
125+
{9B9EE2E5-E6C8-47A8-B610-8C7454B63969}.Release|x64.Build.0 = Release|Any CPU
126+
{9B9EE2E5-E6C8-47A8-B610-8C7454B63969}.Release|x86.ActiveCfg = Release|Any CPU
127+
{9B9EE2E5-E6C8-47A8-B610-8C7454B63969}.Release|x86.Build.0 = Release|Any CPU
100128
EndGlobalSection
101129
GlobalSection(SolutionProperties) = preSolution
102130
HideSolutionNode = FALSE
Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,27 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

3-
<PropertyGroup>
4-
<OutputType>Exe</OutputType>
5-
<TargetFramework>net9.0</TargetFramework>
6-
</PropertyGroup>
3+
<PropertyGroup>
4+
<TargetFramework>net9.0</TargetFramework>
5+
<OutputType>Exe</OutputType>
6+
<WarningsAsErrors>true</WarningsAsErrors>
7+
</PropertyGroup>
78

8-
<ItemGroup>
9-
<Compile Include="DataParser.fs" />
10-
<Compile Include="Charts.fs" />
11-
<Compile Include="ChartMaker.fs" />
12-
<Compile Include="ArgParser.fs" />
13-
<Compile Include="Program.fs" />
14-
</ItemGroup>
9+
<ItemGroup>
10+
<Compile Include="DataParser.fs" />
11+
<Compile Include="Charts.fs" />
12+
<Compile Include="ChartMaker.fs" />
13+
<Compile Include="ArgParser.fs" />
14+
<Compile Include="Program.fs" />
15+
</ItemGroup>
1516

16-
<ItemGroup>
17-
<PackageReference Include="Argu" Version="6.2.5" />
18-
<PackageReference Include="FSharp.Data" Version="6.6.0" />
19-
<PackageReference Include="Plotly.NET" Version="5.1.0" />
20-
<PackageReference Update="FSharp.Core" Version="9.0.300" />
21-
</ItemGroup>
17+
<ItemGroup>
18+
<PackageReference Include="Argu" Version="6.2.5" />
19+
<PackageReference Include="Plotly.NET" Version="5.1.0" />
20+
<PackageReference Include="FSharp.Data" Version="6.6.0" />
21+
</ItemGroup>
2222

23-
</Project>
23+
<ItemGroup>
24+
<PackageReference Update="FSharp.Core" Version="9.0.300" />
25+
</ItemGroup>
26+
27+
</Project>

benchmarks/FSharp.FIO.Benchmarks/FSharp.FIO.Benchmarks.fsproj

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,17 @@
1919
<Compile Include="Program.fs" />
2020
</ItemGroup>
2121

22+
<ItemGroup>
23+
<ProjectReference Include="..\..\src\FSharp.FIO\FSharp.FIO.fsproj" />
24+
<ProjectReference Include="..\..\src\FSharp.FIO.Lib\FSharp.FIO.Lib.fsproj" />
25+
</ItemGroup>
26+
2227
<ItemGroup>
2328
<PackageReference Include="Argu" Version="6.2.5" />
24-
<PackageReference Update="FSharp.Core" Version="9.0.300" />
2529
</ItemGroup>
2630

2731
<ItemGroup>
28-
<ProjectReference Include="..\..\src\FSharp.FIO\FSharp.FIO.fsproj" />
32+
<PackageReference Update="FSharp.Core" Version="9.0.300" />
2933
</ItemGroup>
3034

3135
</Project>

examples/FSharp.FIO.Examples.App/FSharp.FIO.Examples.App.fsproj

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@
1111
</ItemGroup>
1212

1313
<ItemGroup>
14-
<ProjectReference Include="..\..\src\FSharp.FIO\FSharp.FIO.fsproj" />
14+
<ProjectReference Include="..\..\src\FSharp.FIO\FSharp.FIO.fsproj" />
15+
<ProjectReference Include="..\..\src\FSharp.FIO.Lib\FSharp.FIO.Lib.fsproj" />
16+
<ProjectReference Include="..\..\src\FSharp.FIO.App\FSharp.FIO.App.fsproj" />
1517
</ItemGroup>
1618

1719
<ItemGroup>
18-
<PackageReference Update="FSharp.Core" Version="9.0.300" />
20+
<PackageReference Update="FSharp.Core" Version="9.0.300" />
1921
</ItemGroup>
2022

2123
</Project>

examples/FSharp.FIO.Examples.App/Program.fs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -152,24 +152,24 @@ type PingPongMatchApp() =
152152
let pinger (chan1: Channel<Message>) (chan2: Channel<Message>) =
153153
fio {
154154
let! ping = chan1 <-- Ping
155-
do! FConsole.PrintLine ($"pinger sent: %A{ping}", _.Message)
155+
do! FConsole.PrintLineMapError ($"pinger sent: %A{ping}", _.Message)
156156

157157
match! !<-- chan2 with
158-
| Pong -> do! FConsole.PrintLine ($"pinger received: %A{Pong}", _.Message)
158+
| Pong -> do! FConsole.PrintLineMapError ($"pinger received: %A{Pong}", _.Message)
159159
| Ping -> return! !- $"pinger received %A{Ping} when %A{Pong} was expected!"
160160
}
161161

162162
let ponger (chan1: Channel<Message>) (chan2: Channel<Message>) =
163163
fio {
164164
match! !<-- chan1 with
165-
| Ping -> do! FConsole.PrintLine ($"ponger received: %A{Ping}", _.Message)
165+
| Ping -> do! FConsole.PrintLineMapError ($"ponger received: %A{Ping}", _.Message)
166166
| Pong -> return! !- $"ponger received %A{Pong} when %A{Ping} was expected!"
167167

168168
let! sentMsg =
169169
match Random().Next(0, 2) with
170170
| 0 -> chan2 <-- Pong
171171
| _ -> chan2 <-- Ping
172-
do! FConsole.PrintLine ($"ponger sent: %A{sentMsg}", _.Message)
172+
do! FConsole.PrintLineMapError ($"ponger sent: %A{sentMsg}", _.Message)
173173
}
174174

175175
override _.effect =
@@ -450,7 +450,7 @@ type SocketApp(ip: string, port: int) =
450450

451451
override _.effect =
452452
fio {
453-
do! server ip port <~> client ip port
453+
do! client ip port <~> server ip port
454454
}
455455

456456
type WebSocketApp(serverUrl, clientUrl) =
@@ -519,7 +519,7 @@ type WebSocketApp(serverUrl, clientUrl) =
519519

520520
override _.effect =
521521
fio {
522-
do! server serverUrl <~> client clientUrl
522+
do! client clientUrl <~> server serverUrl
523523
}
524524

525525
WelcomeApp().Run ()

examples/FSharp.FIO.Examples/FSharp.FIO.Examples.fsproj

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@
1111
</ItemGroup>
1212

1313
<ItemGroup>
14-
<ProjectReference Include="..\..\src\FSharp.FIO\FSharp.FIO.fsproj" />
14+
<ProjectReference Include="..\..\src\FSharp.FIO\FSharp.FIO.fsproj" />
15+
<ProjectReference Include="..\..\src\FSharp.FIO.Lib\FSharp.FIO.Lib.fsproj" />
1516
</ItemGroup>
1617

1718
<ItemGroup>
18-
<PackageReference Update="FSharp.Core" Version="9.0.300" />
19+
<PackageReference Update="FSharp.Core" Version="9.0.300" />
1920
</ItemGroup>
2021

2122
</Project>

src/FSharp.FIO.App/App.fs

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
(*********************************************************************************************)
2+
(* FIO - A Type-Safe, Purely Functional Effect System for Asynchronous and Concurrent F# *)
3+
(* Copyright (c) 2022-2025 - Daniel "iyyel" Larsen and Technical University of Denmark (DTU) *)
4+
(* All rights reserved *)
5+
(*********************************************************************************************)
6+
7+
/// <summary>
8+
/// Provides application-level helpers and the <c>FIOApp</c> base class for running FIO effects as applications.
9+
/// Includes default runtime, fiber handling, and customizable success/error handlers for effectful entry points.
10+
/// </summary>
11+
module FSharp.FIO.App
12+
13+
open FSharp.FIO.DSL
14+
open FSharp.FIO.Runtime
15+
open FSharp.FIO.Runtime.Concurrent
16+
17+
open System
18+
open System.Threading
19+
open System.Threading.Tasks
20+
21+
// TODO: Is this necessary?
22+
let private maxThreads = 32767
23+
ThreadPool.SetMaxThreads(maxThreads, maxThreads) |> ignore
24+
ThreadPool.SetMinThreads(maxThreads, maxThreads) |> ignore
25+
26+
let private defaultRuntime = Runtime()
27+
28+
let private mergeResult onSuccess onError = function
29+
| Ok res -> onSuccess res
30+
| Error err -> onError err
31+
32+
let private mergeFiber onSuccess onError (fiber: Fiber<'R, 'E>) = task {
33+
let! res = fiber.Task()
34+
return! mergeResult onSuccess onError res
35+
}
36+
37+
let private defaultOnSuccess res = task {
38+
Console.ForegroundColor <- ConsoleColor.DarkGreen
39+
Console.WriteLine $"%A{Ok res}"
40+
Console.ResetColor()
41+
}
42+
43+
let private defaultOnError err = task {
44+
Console.ForegroundColor <- ConsoleColor.DarkRed
45+
Console.WriteLine $"%A{Error err}"
46+
Console.ResetColor()
47+
}
48+
49+
let private defaultFiberHandler fiber = mergeFiber defaultOnSuccess defaultOnError fiber
50+
51+
/// <summary>
52+
/// Abstract base class for FIO applications. Provides effectful entry points and customizable handlers for success and error cases.
53+
/// </summary>
54+
/// <typeparam name="R">The result type of the application effect.</typeparam>
55+
/// <typeparam name="E">The error type of the application effect.</typeparam>
56+
/// <param name="onSuccess">Handler to invoke on success.</param>
57+
/// <param name="onError">Handler to invoke on error.</param>
58+
/// <param name="runtime">The runtime to use for interpretation.</param>
59+
[<AbstractClass>]
60+
type FIOApp<'R, 'E> (onSuccess: 'R -> Task<unit>, onError: 'E -> Task<unit>, runtime: FRuntime) =
61+
let fiberHandler = mergeFiber onSuccess onError
62+
63+
/// <summary>
64+
/// Initializes a new <c>FIOApp</c> with default handlers and runtime.
65+
/// </summary>
66+
new() = FIOApp(defaultOnSuccess, defaultOnError, defaultRuntime)
67+
68+
/// <summary>
69+
/// The main effect to be interpreted by the application.
70+
/// </summary>
71+
/// <returns>The main FIO effect of the application.</returns>
72+
abstract member effect: FIO<'R, 'E>
73+
74+
/// <summary>
75+
/// Runs the given <c>FIOApp</c> instance using its configured runtime and handlers.
76+
/// </summary>
77+
/// <typeparam name="R">The result type of the application effect.</typeparam>
78+
/// <typeparam name="E">The error type of the application effect.</typeparam>
79+
/// <param name="app">The FIOApp instance to run.</param>
80+
static member Run<'R, 'E> (app: FIOApp<'R, 'E>) =
81+
app.Run()
82+
83+
/// <summary>
84+
/// Runs the given FIO effect using the default runtime and handlers.
85+
/// </summary>
86+
/// <typeparam name="R">The result type of the effect.</typeparam>
87+
/// <typeparam name="E">The error type of the effect.</typeparam>
88+
/// <param name="eff">The FIO effect to run.</param>
89+
static member Run<'R, 'E> (eff: FIO<'R, 'E>) =
90+
let fiber = defaultRuntime.Run eff
91+
let task = defaultFiberHandler fiber
92+
task.Wait()
93+
94+
/// <summary>
95+
/// Runs the application effect using the configured runtime and handlers.
96+
/// </summary>
97+
/// <typeparam name="R">The result type of the application effect.</typeparam>
98+
/// <typeparam name="E">The error type of the application effect.</typeparam>
99+
member this.Run<'R, 'E> () =
100+
this.Run runtime
101+
102+
/// <summary>
103+
/// Runs the application effect using the specified runtime and the configured handlers.
104+
/// </summary>
105+
/// <typeparam name="R">The result type of the application effect.</typeparam>
106+
/// <typeparam name="E">The error type of the application effect.</typeparam>
107+
/// <param name="runtime">The runtime to use for interpretation.</param>
108+
member this.Run<'R, 'E> runtime =
109+
let fiber = runtime.Run this.effect
110+
let task = fiberHandler fiber
111+
task.Wait()
112+
113+
/// <summary>
114+
/// Runs the application effect using the specified success and error handlers.
115+
/// </summary>
116+
/// <typeparam name="R">The result type of the application effect.</typeparam>
117+
/// <typeparam name="E">The error type of the application effect.</typeparam>
118+
/// <typeparam name="F">The result type of the handlers.</typeparam>
119+
/// <param name="onSuccess">Handler to invoke on success.</param>
120+
/// <param name="onError">Handler to invoke on error.</param>
121+
member this.Run<'R, 'E, 'F> (onSuccess: 'R -> Task<'F>, onError: 'E -> Task<'F>) =
122+
let fiber = runtime.Run this.effect
123+
let task = mergeFiber onSuccess onError fiber
124+
task.Wait()
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net9.0</TargetFramework>
5+
<GenerateDocumentationFile>true</GenerateDocumentationFile>
6+
<WarningsAsErrors>true</WarningsAsErrors>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<Compile Include="App.fs" />
11+
</ItemGroup>
12+
13+
<ItemGroup>
14+
<ProjectReference Include="..\..\src\FSharp.FIO\FSharp.FIO.fsproj" />
15+
</ItemGroup>
16+
17+
<ItemGroup>
18+
<PackageReference Update="FSharp.Core" Version="9.0.300" />
19+
</ItemGroup>
20+
21+
</Project>

0 commit comments

Comments
 (0)