2
2
// This block of code is omitted in the generated HTML documentation. Use
3
3
// it to define helpers that you do not want to show in the documentation.
4
4
(**
5
- Validation<'Error,'T>
6
- =====================
5
+ Validation<'Error, 'T>
6
+ ======================
7
7
8
- This is similar to Result<'T,'Error> but with accumulative errors semantics, instead of short-circuit.
8
+ This is similar to Result<'T, 'Error> but with accumulative errors semantics, instead of short-circuit.
9
9
10
10
Examples
11
11
--------
@@ -18,72 +18,83 @@ open System
18
18
open FSharpPlus
19
19
open FSharpPlus.Data
20
20
21
- module MovieValidations =
22
- type VError = | MustNotBeEmpty
23
- | MustBeAtLessThanChars of int
24
- | MustBeADate
25
- | MustBeOlderThan of int
26
- | MustBeWithingRange of decimal * decimal
27
- module String =
28
- let nonEmpty ( x : string ) : Validation < VError list , string > =
29
- if String.IsNullOrEmpty x
21
+ module MovieValidations =
22
+ type VError =
23
+ | MustNotBeEmpty
24
+ | MustBeAtLessThanChars of int
25
+ | MustBeADate
26
+ | MustBeOlderThan of int
27
+ | MustBeWithingRange of decimal * decimal
28
+
29
+ module String =
30
+ let nonEmpty ( x : string ) : Validation < VError list , string > =
31
+ if String.IsNullOrEmpty x
30
32
then Failure [ MustNotBeEmpty]
31
33
else Success x
32
- let mustBeLessThan ( i : int ) ( x : string ) : Validation < VError list , string > =
34
+ let mustBeLessThan ( i : int ) ( x : string ) : Validation < VError list , string > =
33
35
if isNull x || x.Length > i
34
36
then Failure [ MustBeAtLessThanChars i]
35
37
else Success x
36
- module Number =
37
- let mustBeWithin ( from , to' ) ( x )=
38
+
39
+ module Number =
40
+ let mustBeWithin ( from , to' ) x =
38
41
if from<= x && x <= to'
39
42
then Success x
40
- else Failure [ MustBeWithingRange ( from, to')]
41
- module DateTime =
42
- let classicMovie year ( d : DateTime )=
43
+ else Failure [ MustBeWithingRange ( from, to')]
44
+
45
+ module DateTime =
46
+ let classicMovie year ( d : DateTime ) =
43
47
if d.Year < year
44
48
then Success d
45
49
else Failure [ MustBeOlderThan year]
46
- let date ( d : DateTime )=
50
+ let date ( d : DateTime ) =
47
51
if d.Date = d
48
52
then Success d
49
53
else Failure [ MustBeADate]
50
- type Genre =
54
+
55
+ type Genre =
51
56
| Classic
52
57
| PostClassic
53
58
| Modern
54
59
| PostModern
55
60
| Contemporary
61
+
56
62
type Movie = {
57
63
Id: int
58
64
Title: String
59
65
ReleaseDate: DateTime
60
66
Description: String
61
67
Price: decimal
62
68
Genre: Genre
63
- }
64
- with static member Create ( id , title , releaseDate , description , price , genre ): Validation < VError list , Movie > =
65
- fun title releaseDate description price -> { Id= id; Title= title; ReleaseDate= releaseDate; Description= description; Price= price; Genre= genre }
69
+ } with
70
+ static member Create ( id , title , releaseDate , description , price , genre ) : Validation < VError list , Movie > =
71
+ fun title releaseDate description price -> { Id = id; Title = title; ReleaseDate = releaseDate; Description = description; Price = price; Genre = genre }
66
72
<!> String.nonEmpty title <* String.mustBeLessThan 100 title
67
73
<*> DateTime.classicMovie 1960 releaseDate <* DateTime.date releaseDate
68
74
<*> String.nonEmpty description <* String.mustBeLessThan 1000 description
69
75
<*> Number.mustBeWithin ( 0.0 m, 999.99 m) price
70
76
71
- let newRelease = Movie.Create( 1 , " Midsommar" , DateTime( 2019 , 6 , 24 ), " Midsommar is a 2019 folk horror film written..." , 1 m, Classic) //Failure [MustBeOlderThan 1960]
72
- let oldie = Movie.Create( 2 , " Modern Times" , DateTime( 1936 , 2 , 5 ), " Modern Times is a 1936 American comedy film..." , 1 m, Classic) // Success..
73
- let titleToLong = Movie.Create( 3 , String.Concat ( seq { 1 .. 110 }), DateTime( 1950 , 1 , 1 ), " 11" , 1 m, Classic) //Failure [MustBeAtLessThanChars 100]
77
+ let newRelease = Movie.Create ( 1 , " Midsommar" , DateTime ( 2019 , 6 , 24 ), " Midsommar is a 2019 folk horror film written..." , 1 m, Classic) //Failure [MustBeOlderThan 1960]
78
+ let oldie = Movie.Create ( 2 , " Modern Times" , DateTime ( 1936 , 2 , 5 ), " Modern Times is a 1936 American comedy film..." , 1 m, Classic) // Success..
79
+ let titleToLong = Movie.Create ( 3 , String.Concat ( seq { 1 .. 110 }), DateTime ( 1950 , 1 , 1 ), " 11" , 1 m, Classic) //Failure [MustBeAtLessThanChars 100]
80
+
81
+
82
+ module Person =
83
+
84
+ type Name = { unName: String }
85
+ with static member create s = { unName = s }
86
+
87
+ type Email = { unEmail: String }
88
+ with static member create s = { unEmail = s }
74
89
75
- module Person =
76
- type Name = { unName : String }
77
- with static member create s = { unName= s}
78
- type Email = { unEmail : String }
79
- with static member create s = { unEmail= s}
80
90
type Age = { unAge : int }
81
- with static member create i = { unAge= i }
91
+ with static member create i = { unAge = i }
82
92
83
- type Person = { name : Name
84
- email : Email
85
- age : Age }
86
- with static member create name email age = { name= name; email= email; age= age }
93
+ type Person = {
94
+ name: Name
95
+ email: Email
96
+ age: Age }
97
+ with static member create name email age = { name = name; email = email; age = age }
87
98
88
99
89
100
type Error =
@@ -92,21 +103,21 @@ module Person=
92
103
| AgeBetween0and120
93
104
94
105
// Smart constructors
95
- let mkName s =
106
+ let mkName s =
96
107
let l = length s
97
108
if ( l >= 1 && l <= 50 )
98
109
then Success <| Name.create s
99
- else Failure [ NameBetween1And50 ]
110
+ else Failure [ NameBetween1And50]
100
111
101
- let mkEmail s =
112
+ let mkEmail s =
102
113
if String.contains '@' s
103
114
then Success <| Email.create s
104
- else Failure [ EmailMustContainAtChar ]
115
+ else Failure [ EmailMustContainAtChar]
105
116
106
- let mkAge a =
117
+ let mkAge a =
107
118
if ( a >= 0 && a <= 120 )
108
119
then Success <| Age.create a
109
- else Failure [ AgeBetween0and120 ]
120
+ else Failure [ AgeBetween0and120]
110
121
111
122
let mkPerson pName pEmail pAge =
112
123
Person.create
@@ -147,36 +158,37 @@ module Person=
147
158
module Email =
148
159
149
160
// ***** Types *****
150
- type AtString = AtString of string
151
- type PeriodString = PeriodString of string
152
- type NonEmptyString = NonEmptyString of string
161
+ type AtString = AtString of string
162
+ type PeriodString = PeriodString of string
163
+ type NonEmptyString = NonEmptyString of string
153
164
154
- type Email = Email of string
165
+ type Email = Email of string
155
166
156
- type VError = | MustNotBeEmpty
157
- | MustContainAt
158
- | MustContainPeriod
167
+ type VError =
168
+ | MustNotBeEmpty
169
+ | MustContainAt
170
+ | MustContainPeriod
159
171
160
172
// ***** Base smart constructors *****
161
173
// String must contain an '@' character
162
- let atString ( x : string ) : Validation < VError list , AtString > =
174
+ let atString ( x : string ) : Validation < VError list , AtString > =
163
175
if String.contains '@' x then Success <| AtString x
164
176
else Failure [ MustContainAt]
165
177
166
178
// String must contain an '.' character
167
- let periodString ( x : string ) : Validation < VError list , PeriodString > =
179
+ let periodString ( x : string ) : Validation < VError list , PeriodString > =
168
180
if String.contains '.' x
169
181
then Success <| PeriodString x
170
182
else Failure [ MustContainPeriod]
171
183
172
184
// String must not be empty
173
- let nonEmptyString ( x : string ) : Validation < VError list , NonEmptyString > =
174
- if not <| String.IsNullOrEmpty x
185
+ let nonEmptyString ( x : string ) : Validation < VError list , NonEmptyString > =
186
+ if not <| String.IsNullOrEmpty x
175
187
then Success <| NonEmptyString x
176
188
else Failure [ MustNotBeEmpty]
177
189
178
190
// ***** Combining smart constructors *****
179
- let email ( x : string ) : Validation < VError list , Email > =
191
+ let email ( x : string ) : Validation < VError list , Email > =
180
192
result ( Email x) <*
181
193
nonEmptyString x <*
182
194
atString x <*
0 commit comments