You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardexpand all lines: README.md
+120-19
Original file line number
Diff line number
Diff line change
@@ -5,9 +5,9 @@
5
5
Danom is a C# library that provides monadic structures to simplify functional programming patterns in C#, that enforces exhaustive matching by preventing direct value access (this is good).
6
6
7
7
## Key Features
8
-
- Implementation of common monads like `Option`, `Result`, and `ResultOption`.
8
+
- Implementation of common monads like [Option](#option), [Result](#result), and [ResultOption](#resultoption).
9
9
- Fluent API for chaining operations.
10
-
- Error handling with monads.
10
+
-[Error handling](#using-results) with monads.
11
11
- Integration with async/await for asynchronous operations.
12
12
13
13
## Design Goals
@@ -16,9 +16,45 @@ Danom is a C# library that provides monadic structures to simplify functional pr
16
16
-**Interoperability**: Seamless integration with existing C# code and libraries.
17
17
-**Durability**: Prevent direct use of internal value, enforcing exhaustive matching.
18
18
19
-
## Options
19
+
## Getting Started
20
20
21
-
Represents when an actual value might not exist for a value or named variable. An option has an underlying type and can hold a value of that type, or it might not have a value.
21
+
Install the [Danom](https://www.nuget.org/packages/Danom/) NuGet package:
?Result<int, string>.Error("Cannot divide by zero")
48
+
:Result<int, string>.Ok(numerator/denominator);
49
+
50
+
TryDivide(10, 2)
51
+
.Match(
52
+
ok: x=>Console.WriteLine("Result: {0}", x),
53
+
error: e=>Console.WriteLine("Error: {0}", e));
54
+
55
+
## Option
56
+
57
+
Representswhenanactualvaluemightnotexistfor a value or named variable. An option has an underlying type and can hold a value of that type, or it might not have a value. Options are a fantastic means of reducing primitive congestion in your code, and they are a much safer way to handle null values and virutally eliminate null reference exceptions.
22
58
23
59
### Creating Options
24
60
@@ -28,7 +64,7 @@ var option = Option<int>.Some(5);
28
64
varoptionNone=Option<int>.None();
29
65
```
30
66
31
-
### Using Options
67
+
### Using Option
32
68
33
69
Options are commonly used when a operation might not return a value.
34
70
@@ -49,46 +85,111 @@ TryFind(nums, x => x == 1)
49
85
none: () =>Console.WriteLine("Did not find number"));
50
86
51
87
// Mapping the value
52
-
varoptionSum=
88
+
Option<int>optionSum=
53
89
TryFind(nums, x=>x==1)
54
90
.Map(x=>x+1);
55
91
56
92
// Binding the option
57
-
varoptionBindSum=
93
+
Option<int>optionBindSum=
58
94
TryFind(nums, x=>x==1)
59
95
.Bind(num1=>
60
96
TryFind(nums, x=>x==2)
61
97
.Map(num2=>num1+num2));
62
98
63
99
// Handling "None"
64
-
varoptionDefault=
100
+
Option<int>optionDefault=
65
101
TryFind(nums, x=>x==4)
66
102
.DefaultValue(99);
67
103
68
-
varoptionDefaultWith=
104
+
Option<int>optionDefaultWith=
69
105
TryFind(nums, x=>x==4)
70
106
.DefaultWith(() =>99); // useful if creating the value is expensive
71
107
72
-
varoptionOrElse=
108
+
Option<int>optionOrElse=
73
109
TryFind(nums, x=>x==4)
74
-
.OrElse(Option.Some(99));
110
+
.OrElse(Option<int>.Some(99));
75
111
76
-
varoptionOrElseWith=
112
+
Option<int>optionOrElseWith=
77
113
TryFind(nums, x=>x==4)
78
-
.OrElseWith(() =>99);
114
+
.OrElseWith(() =>Option<int>.Some(99)); // useful if creating the value is expensive
79
115
```
80
116
81
-
## Results
117
+
## Result
118
+
119
+
Represents the result of an operation that can either succeed or fail. These results can be chained together allowing you to form error-tolerant pipelines. This lets you break up functionality like this into small pieces which are as composable as you need them to be. Also benefiting from the exhaustive matching.
?Result<int, string>.Error("Cannot divide by zero")
142
+
:Result<int, string>.Ok(numerator/denominator);
143
+
144
+
// Exhasutive matching
145
+
TryDivide(10, 2)
146
+
.Match(
147
+
ok: x=>Console.WriteLine("Result: {0}", x),
148
+
error: e=>Console.WriteLine("Error: {0}", e));
149
+
150
+
// Mapping the value
151
+
Result<int, string>resultSum=
152
+
TryDivide(10, 2)
153
+
.Map(x=>x+1);
154
+
155
+
// Binding the result (i.e., when a nested operation also returns a Result)
156
+
Result<int, string>resultBindSum=
157
+
TryDivide(10, 2)
158
+
.Bind(num1=>
159
+
TryDivide(20, 2)
160
+
.Map(num2=>
161
+
num1+num2));
162
+
163
+
// Handling errors
164
+
Result<int, string>resultDefault=
165
+
TryDivide(10, 0)
166
+
.DefaultValue(99);
167
+
168
+
Result<int, string>resultDefaultWith=
169
+
TryDivide(10, 0)
170
+
.DefaultWith(() =>99); // useful if creating the value is expensive
171
+
172
+
Result<int, string>resultOrElse=
173
+
TryDivide(10, 0)
174
+
.OrElse(Result<int, string>.Ok(99));
175
+
176
+
Result<int, string>resultOrElseWith=
177
+
TryDivide(10, 0)
178
+
.OrElseWith(() =>
179
+
Result<int, string>.Ok(99)); // useful if creating the value is expensive
180
+
```
181
+
182
+
Since error messages are frequently represented as string collections, often with keys (e.g., for validation), the `ResultErrors` type is provided to simplify Result creation. The flexible constructor allows errors to be initialized with a single string, a collection of strings, or a key-value pair.
0 commit comments