public void If_WithFuncOfBooleanAndThenMonadType() // M<T> If<T>(Func<Boolean>, M<T>)
        {
            var spec = MethodSpecificationBuilder
                       .Named("If")
                       .IsStatic()
                       .IsPublic()
                       .IsNotExtensionMethod()
                       .IsOpenGeneric()

                       .GenericArgument(ga => ga
                                        .Named("T")
                                        .AtIndex(0)
                                        .CanBeReferenceType()
                                        .CanBeValueType())

                       .HasParameters(2)
                       .Parameter((m, p) => p
                                  .Named("predicate")
                                  .AtIndex(0)
                                  .Type(t => t.IsEqualTo(typeof(Func <bool>))))

                       .Parameter((m, p) => p
                                  .Named("then")
                                  .AtIndex(1)
                                  .Type(t => t.IsEqualTo(m.ReturnType)))

                       .Returns((m, t) => t
                                .IsEqualTo(MonadType.MakeGenericType(m.ReturnType.GetGenericArguments())));

            Assert.IsNotNull(ExtensionType.GetMethods().Single(spec.ToFunc()));
        }
        protected MonadicLawsTestFixture(Type monadType, Type extensionType)
        {
            MonadType     = Guard.NotNull(monadType, "monadType");
            ExtensionType = Guard.NotNull(extensionType, "extensionType");

            OpenValueType = MonadType.GetGenericArguments()[0];
        }
        public void Defer_WithFunctionThatReturnsMonadType() // M<T> Defer<T>(Func<M<T>>)
        {
            var spec = MethodSpecificationBuilder
                       .Named("Defer")
                       .IsStatic()
                       .IsNotExtensionMethod()
                       .IsPublic()
                       .IsOpenGeneric()

                       .GenericArgument(ga => ga
                                        .Named("T")
                                        .AtIndex(0)
                                        .CanBeReferenceType()
                                        .CanBeValueType())

                       .HasParameters(1)
                       .Parameter((m, p) => p
                                  .Named("computation")
                                  .AtIndex(0)
                                  .Type(t => t.IsEqualTo(typeof(Func <>).MakeGenericType(m.ReturnType))))

                       .Returns((m, t) => t
                                .IsEqualTo(MonadType.MakeGenericType(m.ReturnType.GetGenericArguments())));

            Assert.IsNotNull(ExtensionType.GetMethods().Single(spec.ToFunc()));
        }
        public MaybeMonadContractTests(Type monadType, Type extensionType)
            : base(monadType, extensionType)
        {
            ValueType = typeof(string);

            ClosedMonadType = MonadType.MakeGenericType(GetTypeArguments(ValueType));
        }
 public void MonadType_ImplementsImplicitConversionOperatorToValueType()
 {
     Assert.IsNotNull(MonadType.GetMethodsWithParameters()
                      .Where(x => x.Method.Name == "op_Implicit")
                      .Where(x => x.Parameters.Count == 1)
                      .Where(x => x.Parameters[0].ParameterType == MonadType.MakeGenericType(GetTypeArguments(typeof(Unit))))
                      .Single(x => x.Method.ReturnType == MonadType));
 }
        public void ReturnsValue_IfTypeIsUnit()
        {
            IMaybe maybe = FormatterServices.GetSafeUninitializedObject(MonadType.MakeGenericType(GetTypeArguments(typeof(Unit)))) as IMaybe;

            Assert.IsNotNull(maybe);
            Assert.IsTrue(maybe.HasValue);
            Assert.AreEqual(new Unit(), maybe.Value);
        }
        public void MonadType_FirstTypeArgument_IsTypeOfUnderlyingValue()
        {
            // First argument of the type of the underlying Value
            var method = MonadType.GetMethodsWithParameters()
                         .Where(x => x.Method.IsSpecialName && x.Method.Name == "get_Value")
                         .Single(x => x.Parameters.Count == 0)
                         .Method;

            Assert.IsTrue(method.ReturnType == OpenValueType);
        }
        protected Type[] GetTypeArguments(Type firstTypeArgument)
        {
            Guard.NotNull(firstTypeArgument, "firstTypeArgument");

            return(new[] { firstTypeArgument }.Concat(Enumerable.Repeat(typeof(Unit), MonadType.GetGenericArguments().Length - 1)).ToArray());
        }
 public void HasPublicConstructor_ThatTakesAFunctionThatYieldsTheClosedMonadType()
 {
     MonadType.GetConstructorsWithParameters()
     .Single(x => x.Parameters.Count == 1 &&
             x.Parameters[0].ParameterType == typeof(Func <>).MakeGenericType(MonadType));
 }
 public void HasPublicConstructor_ThatTakesValue()
 {
     MonadType.GetConstructorsWithParameters()
     .Single(x => x.Parameters.Count == 1 &&
             x.Parameters[0].ParameterType == OpenValueType);
 }