diff --git a/docsrc/content/type-validation.fsx b/docsrc/content/type-validation.fsx index a6309b789..b230e55d3 100644 --- a/docsrc/content/type-validation.fsx +++ b/docsrc/content/type-validation.fsx @@ -2,10 +2,10 @@ // This block of code is omitted in the generated HTML documentation. Use // it to define helpers that you do not want to show in the documentation. (** -Validation<'Error,'T> -===================== +Validation<'Error, 'T> +====================== -This is similar to Result<'T,'Error> but with accumulative errors semantics, instead of short-circuit. +This is similar to Result<'T, 'Error> but with accumulative errors semantics, instead of short-circuit. Examples -------- @@ -18,41 +18,47 @@ open System open FSharpPlus open FSharpPlus.Data -module MovieValidations= - type VError= | MustNotBeEmpty - | MustBeAtLessThanChars of int - | MustBeADate - | MustBeOlderThan of int - | MustBeWithingRange of decimal*decimal - module String= - let nonEmpty (x:string) : Validation = - if String.IsNullOrEmpty x +module MovieValidations = + type VError = + | MustNotBeEmpty + | MustBeAtLessThanChars of int + | MustBeADate + | MustBeOlderThan of int + | MustBeWithingRange of decimal * decimal + + module String = + let nonEmpty (x:string) : Validation = + if String.IsNullOrEmpty x then Failure [MustNotBeEmpty] else Success x - let mustBeLessThan (i:int) (x:string) : Validation = + let mustBeLessThan (i: int) (x: string) : Validation = if isNull x || x.Length > i then Failure [MustBeAtLessThanChars i] else Success x - module Number= - let mustBeWithin (from,to') (x)= + + module Number = + let mustBeWithin (from, to') x = if from<= x && x <= to' then Success x - else Failure [MustBeWithingRange (from,to')] - module DateTime= - let classicMovie year (d:DateTime)= + else Failure [MustBeWithingRange (from, to')] + + module DateTime = + let classicMovie year (d: DateTime) = if d.Year < year then Success d else Failure [MustBeOlderThan year] - let date (d:DateTime)= + let date (d: DateTime) = if d.Date = d then Success d else Failure [MustBeADate] - type Genre= - |Classic - |PostClassic - |Modern - |PostModern - |Contemporary + + type Genre = + | Classic + | PostClassic + | Modern + | PostModern + | Contemporary + type Movie = { Id: int Title: String @@ -60,30 +66,35 @@ module MovieValidations= Description: String Price: decimal Genre: Genre - } - with static member Create(id,title,releaseDate,description,price,genre): Validation = - fun title releaseDate description price->{ Id=id;Title=title;ReleaseDate=releaseDate;Description=description;Price=price;Genre=genre } + } with + static member Create (id, title, releaseDate, description, price, genre) : Validation = + fun title releaseDate description price -> { Id = id; Title = title; ReleaseDate = releaseDate; Description = description; Price = price; Genre = genre } String.nonEmpty title <* String.mustBeLessThan 100 title <*> DateTime.classicMovie 1960 releaseDate <* DateTime.date releaseDate <*> String.nonEmpty description <* String.mustBeLessThan 1000 description <*> Number.mustBeWithin (0.0m, 999.99m) price - let newRelease = Movie.Create(1,"Midsommar",DateTime(2019,6,24),"Midsommar is a 2019 folk horror film written...",1m,Classic) //Failure [MustBeOlderThan 1960] - let oldie = Movie.Create(2,"Modern Times",DateTime(1936,2,5),"Modern Times is a 1936 American comedy film...",1m,Classic) // Success.. - let titleToLong = Movie.Create(3, String.Concat (seq{ 1..110 }), DateTime(1950,1,1),"11",1m,Classic) //Failure [MustBeAtLessThanChars 100] + let newRelease = Movie.Create (1, "Midsommar", DateTime (2019, 6, 24), "Midsommar is a 2019 folk horror film written...", 1m, Classic) //Failure [MustBeOlderThan 1960] + let oldie = Movie.Create (2, "Modern Times", DateTime (1936, 2, 5), "Modern Times is a 1936 American comedy film...", 1m, Classic) // Success.. + let titleToLong = Movie.Create (3, String.Concat (seq { 1..110 }), DateTime (1950, 1, 1), "11", 1m, Classic) //Failure [MustBeAtLessThanChars 100] + + +module Person = + + type Name = { unName: String } + with static member create s = {unName = s } + + type Email = { unEmail: String } + with static member create s = { unEmail = s } -module Person= - type Name = { unName : String } - with static member create s={unName=s} - type Email = { unEmail : String } - with static member create s={unEmail=s} type Age = { unAge : int } - with static member create i={unAge=i} + with static member create i = { unAge = i } - type Person = { name : Name - email : Email - age : Age } - with static member create name email age={name=name;email=email;age=age } + type Person = { + name: Name + email: Email + age: Age } + with static member create name email age = { name = name; email = email; age = age } type Error = @@ -92,21 +103,21 @@ module Person= | AgeBetween0and120 // Smart constructors - let mkName s = + let mkName s = let l = length s if (l >= 1 && l <= 50) then Success <| Name.create s - else Failure [ NameBetween1And50 ] + else Failure [NameBetween1And50] - let mkEmail s = + let mkEmail s = if String.contains '@' s then Success <| Email.create s - else Failure [ EmailMustContainAtChar ] + else Failure [EmailMustContainAtChar] - let mkAge a = + let mkAge a = if (a >= 0 && a <= 120) then Success <| Age.create a - else Failure [ AgeBetween0and120 ] + else Failure [AgeBetween0and120] let mkPerson pName pEmail pAge = Person.create @@ -147,36 +158,37 @@ module Person= module Email = // ***** Types ***** - type AtString = AtString of string - type PeriodString = PeriodString of string - type NonEmptyString = NonEmptyString of string + type AtString = AtString of string + type PeriodString = PeriodString of string + type NonEmptyString = NonEmptyString of string - type Email = Email of string + type Email = Email of string - type VError = | MustNotBeEmpty - | MustContainAt - | MustContainPeriod + type VError = + | MustNotBeEmpty + | MustContainAt + | MustContainPeriod // ***** Base smart constructors ***** // String must contain an '@' character - let atString (x:string) : Validation = + let atString (x: string) : Validation = if String.contains '@' x then Success <| AtString x else Failure [MustContainAt] // String must contain an '.' character - let periodString (x:string) : Validation = + let periodString (x: string) : Validation = if String.contains '.' x then Success <| PeriodString x else Failure [MustContainPeriod] // String must not be empty - let nonEmptyString (x:string) : Validation = - if not <| String.IsNullOrEmpty x + let nonEmptyString (x: string) : Validation = + if not <| String.IsNullOrEmpty x then Success <| NonEmptyString x else Failure [MustNotBeEmpty] // ***** Combining smart constructors ***** - let email (x:string) : Validation = + let email (x: string) : Validation = result (Email x) <* nonEmptyString x <* atString x <*