public void Part3() {
     var person = new Person(
         gender: Gender.Male,
         age: 59,
         clothes: FSharpSet.Create("Jeans"),
         sobriety: Sobriety.Paralytic);
     var cost = GayBar.CostToEnter(person);
     Assert.AreEqual(FSharpChoice.Errors<decimal>("Too old!", "Smarten up!", "Sober up!"), cost);
 }
 // PERFORM THE CHECKS USING Monadic SUGAR (LINQ)
 public static FSharpChoice<decimal, NonEmptyList<string>> CostToEnter(Person p) {
     return from a in Club.CheckAge(p)
            from b in Club.CheckClothes(a)
            from c in Club.CheckSobriety(b)
            select c.Gender == Gender.Female ? 0m : 5m;
 }
 public static FSharpChoice<decimal, NonEmptyList<string>> CostToEnter(Person p) {
     return 
         FSharpList.Create(Club.CheckAge, Club.CheckClothes, Club.CheckSobriety, CheckGender)
             .SelectMValidation(check => check(p))
             .Select(x => x[0].Age + 1.5m);
 }
        public void Part2() {
            var daveParalytic = new Person(
                age: Test1.Dave.Age,
                clothes: Test1.Dave.Clothes,
                gender: Test1.Dave.Gender,
                sobriety: Sobriety.Paralytic);
            var costDaveParalytic = ClubTropicana.CostToEnter(daveParalytic);
            Assert.AreEqual(FSharpChoice.Errors<decimal>("Too old!", "Sober up!"), costDaveParalytic);

            var costRuby = ClubTropicana.CostToEnter2(Test1.Ruby);
            Assert.AreEqual(FSharpChoice.Ok(0m), costRuby);
        }
 public static FSharpChoice<decimal, NonEmptyList<string>> CostToEnter2(Person p) {
     return CostByGender.Curry().ReturnValidation()
         .ApValidation(Club.CheckAge(p))
         .ApValidation(Club.CheckClothes(p))
         .ApValidation(Club.CheckSobriety(p));
 }
 //PERFORM THE CHECKS USING applicative functors, accumulating failure via a monoid
 // using LINQ sugar
 public static FSharpChoice<decimal, NonEmptyList<string>> CostToEnter(Person p) {
     return from c in Club.CheckAge(p)
            join x in Club.CheckClothes(p) on 1 equals 1
            join y in Club.CheckSobriety(p) on 1 equals 1
            select c.Gender == Gender.Female ? 0m : 7.5m;
 }
        public void Part1() {
            var costDave = ClubbedToDeath.CostToEnter(Dave);
            Assert.AreEqual(FSharpChoice.Error<decimal>("Too old!"), costDave);

            var costKen = ClubbedToDeath.CostToEnter(Ken);
            Assert.AreEqual(FSharpChoice.Ok(5m), costKen);

            var costRuby = ClubbedToDeath.CostToEnter(Ruby);
            Assert.AreEqual(FSharpChoice.Ok(0m), costRuby);

            var Ruby17 = new Person(
                age: 17,
                clothes: Ruby.Clothes,
                sobriety: Ruby.Sobriety,
                gender: Ruby.Gender);
            var costRuby17 = ClubbedToDeath.CostToEnter(Ruby17);
            Assert.AreEqual(FSharpChoice.Error<decimal>("Too young!"), costRuby17);

            var KenUnconscious = new Person(
                age: Ken.Age,
                clothes: Ken.Clothes,
                gender: Ken.Gender,
                sobriety: Sobriety.Unconscious);
            var costKenUnconscious = ClubbedToDeath.CostToEnter(KenUnconscious);
            Assert.AreEqual(FSharpChoice.Error<decimal>("Sober up!"), costKenUnconscious);

            /**
             * The thing to note here is how the Validations can be composed together in a computation expression.
             * The type system is making sure that failures flow through your computation in a safe manner.
             */
        }