 
     func testApplicative() {
         // pure id <*> v = v
-        property("identity law") <- forAll { (optional: String?) in
-            let lhs = pure(id) <*> optional
-            let rhs = optional
+        property("identity law") <- forAll { (x: String?) in
+            let lhs = pure(id) <*> x
+            let rhs = x
 
             return lhs == rhs
         }
 
         // pure f <*> pure x = pure (f x)
-        property("homomorphism law") <- forAll { (string: String) in
-            let lhs: String? = pure(append) <*> pure(string)
-            let rhs: String? = pure(append(string))
+        property("homomorphism law") <- forAll { (x: String, fa: ArrowOf<String, String>) in
+            let f = fa.getArrow
+
+            let lhs: String? = pure(f) <*> pure(x)
+            let rhs: String? = pure(f(x))
 
             return rhs == lhs
         }
 
-        // u <*> pure y = pure ($ y) <*> u
-        property("interchange law") <- forAll { (string: String) in
-            let lhs: String? = pure(append) <*> pure(string)
-            let rhs: String? = pure({ $0(string) }) <*> pure(append)
+        // f <*> pure x = pure ($ x) <*> f
+        property("interchange law") <- forAll { (x: String, fa: OptionalOf<ArrowOf<String, String>>) in
+            let f = fa.getOptional?.getArrow
+
+            let lhs = f <*> pure(x)
+            let rhs = pure({ $0(x) }) <*> f
 
             return lhs == rhs
         }
 
-        // u <*> (v <*> w) = pure (.) <*> u <*> v <*> w
-        property("compospropertyion law") <- forAll { (optional: String?) in
-            let lhs = pure(append) <*> (pure(prepend) <*> optional)
-            let rhs = pure(curry(compose)) <*> pure(append)  <*> pure(prepend) <*> optional
+        // f <*> (g <*> x) = pure (.) <*> f <*> g <*> x
+        property("composition law") <- forAll { (o: OptionalOf<String>, fa: OptionalOf<ArrowOf<String, String>>, fb: OptionalOf<ArrowOf<String, String>>) in
+            let x = o.getOptional
+            let f = fa.getOptional?.getArrow
+            let g = fb.getOptional?.getArrow
+
+            let lhs = f <*> (g <*> x)
+            let rhs = pure(curry(compose)) <*> f <*> g <*> x
 
             return lhs == rhs
         }


    func testMonad() {
        // return x >>= f = f x
        property("left identity law") <- forAll { (string: String) in
            let lhs: String? = pure(string) >>- compose(append, pure)
            let rhs: String? = compose(append, pure)(string)

            return lhs == rhs
        }

        // m >>= return = m
        property("right identity law") <- forAll { (optional: String?) in
            let lhs = optional >>- pure
            let rhs = optional

            return lhs == rhs
        }

        // (m >>= f) >>= g = m >>= (\x -> f x >>= g)
        property("associativity law") <- forAll { (optional: String?) in
            let lhs = (optional >>- compose(append, pure)) >>- compose(prepend, pure)
            let rhs = optional >>- { x in compose(append, pure)(x) >>- compose(prepend, pure) }

            return lhs == rhs
        }

class OptionalSpec: XCTestCase {
    func testFunctor() {
        // fmap id = id
        property("identity law") <- forAll { (x: String?) in
            let lhs = id <^> x
            let rhs = x

            return lhs == rhs
        }

        // fmap (f . g) = (fmap f) . (fmap g)
        property("function composition law") <- forAll { (o: OptionalOf<String>, fa: ArrowOf<String, String>, fb: ArrowOf<String, String>) in
            let f = fa.getArrow
            let g = fb.getArrow
            let x = o.getOptional

            let lhs = compose(f, g) <^> x
            let rhs = compose(curry(<^>)(f), curry(<^>)(g))(x)

            return lhs == rhs
        }
