public static Result<Person, string> CheckAge(Person p)
 {
     if (p.Age < 18)
         return Result.FailWith<Person, string>("Too young!");
     if (p.Age > 40)
         return Result.FailWith<Person, string>("Too old!");
     return Result.Succeed<Person, string>(p);
 }
        public void Part1()
        {
            var Dave = new Person(Gender.Male, 41, new List<string> { "Tie", "Jeans" }, Sobriety.Sober);
            var costDave = ClubbedToDeath.CostToEnter(Dave);
            "Too old!".ShouldBeEquivalentTo(costDave.FailedWith().First());

            var Ken = new Person(Gender.Male, 28, new List<string> { "Tie", "Shirt" }, Sobriety.Tipsy);
            var costKen = ClubbedToDeath.CostToEnter(Ken);
            5m.ShouldBeEquivalentTo(costKen.SucceededWith());

            var Ruby = new Person(Gender.Female, 25, new List<string> { "High heels" }, Sobriety.Tipsy);
            var costRuby = ClubbedToDeath.CostToEnter(Ruby);
            costRuby.Match(
                (x, msgs) =>
                {
                    0m.ShouldBeEquivalentTo(x);
                },
                msgs =>
                {
                    Assert.True(false, "fail");
                });

            var Ruby17 = new Person(Ruby.Gender, 17, Ruby.Clothes, Ruby.Sobriety);
            var costRuby17 = ClubbedToDeath.CostToEnter(Ruby17);
            "Too young!".ShouldAllBeEquivalentTo(costRuby17.FailedWith().First());

            var KenUnconscious = new Person(Ken.Gender, Ken.Age, Ken.Clothes, Sobriety.Unconscious);
            var costKenUnconscious = ClubbedToDeath.CostToEnter(KenUnconscious);
            costKenUnconscious.Match(
                (x, msgs) =>
                {
                    Assert.True(false, "fail");
                },
                msgs =>
                {
                    "Sober up!".ShouldBeEquivalentTo(msgs.First());
                });
        }
 public static Result<Person, string> CheckSobriety(Person p)
 {
     if (new[] { Sobriety.Drunk, Sobriety.Paralytic, Sobriety.Unconscious }.Contains(p.Sobriety))
         return Result.FailWith<Person, string>("Sober up!");
     return Result.Succeed<Person, string>(p);
 }
 public static Result<Person, string> CheckClothes(Person p)
 {
     if (p.Gender == Gender.Male && !p.Clothes.Contains("Tie"))
         return Result.FailWith<Person, string>("Smarten up!");
     if (p.Gender == Gender.Female && p.Clothes.Contains("Trainers"))
         return Result.FailWith<Person, string>("Wear high heels!");
     return Result.Succeed<Person, string>(p);
 }
 public static Result<decimal, 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;
 }