 public func equal<T: Equatable>(_ expectedValue: [T]?) -> Predicate<[T]> {
     return Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in
         let actualValue = try actualExpression.evaluate()
-        if expectedValue == nil || actualValue == nil {
-            if expectedValue == nil && actualValue != nil {
-                return PredicateResult(
-                    status: .fail,
-                    message: msg.appendedBeNilHint()
-                )
-            }
-            return PredicateResult(
-                status: .fail,
-                message: msg
-            )
-        }
-        return PredicateResult(
-            bool: expectedValue! == actualValue!,
-            message: msg
-        )
+        switch (expectedValue, actualValue) {
+        case (nil, _?):
+            return PredicateResult(status: .fail, message: msg.appendedBeNilHint())
+        case (nil, nil), (_, nil):
+            return PredicateResult(status: .fail, message: msg)
+        case (let expected?, let actual?):
+            let matches = expected == actual
+            return PredicateResult(bool: matches, message: msg)
+        }
     }
 }
 
 /// A Nimble matcher allowing comparison of collection with optional type
 public func equal<T: Equatable>(_ expectedValue: [T?]) -> Predicate<[T?]> {
     return Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in
-        if let actualValue = try actualExpression.evaluate() {
-            let doesNotMatch = PredicateResult(
-                status: .doesNotMatch,
-                message: msg
-            )
-
-            if expectedValue.count != actualValue.count {
+        guard let actualValue = try actualExpression.evaluate() else {
+            return PredicateResult(
+                status: .fail,
+                message: msg.appendedBeNilHint()
+            )
+        }
+
+        let doesNotMatch = PredicateResult(
+            status: .doesNotMatch,
+            message: msg
+        )
+
+        if expectedValue.count != actualValue.count {
+            return doesNotMatch
+        }
+
+        for (index, item) in actualValue.enumerated() {
+            let otherItem = expectedValue[index]
+            if item == nil && otherItem == nil {
+                continue
+            } else if item == nil && otherItem != nil {
+                return doesNotMatch
+            } else if item != nil && otherItem == nil {
+                return doesNotMatch
+            } else if item! != otherItem! {
                 return doesNotMatch
             }
-
-            for (index, item) in actualValue.enumerated() {
-                let otherItem = expectedValue[index]
-                if item == nil && otherItem == nil {
-                    continue
-                } else if item == nil && otherItem != nil {
-                    return doesNotMatch
-                } else if item != nil && otherItem == nil {
-                    return doesNotMatch
-                } else if item! != otherItem! {
-                    return doesNotMatch
-                }
-            }
-
-            return PredicateResult(
-                status: .matches,
-                message: msg
-            )
-        } else {
-            return PredicateResult(
-                status: .fail,
-                message: msg.appendedBeNilHint()
-            )
-        }
+        }
+
+        return PredicateResult(
+            status: .matches,
+            message: msg
+        )
     }
 }
 

public func equal<T: Equatable>(_ expectedValue: T?) -> Predicate<T> {
    return Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in
        let actualValue = try actualExpression.evaluate()
        let matches = actualValue == expectedValue && expectedValue != nil
        if expectedValue == nil || actualValue == nil {
            if expectedValue == nil && actualValue != nil {
                return PredicateResult(
                    status: .fail,
                    message: msg.appendedBeNilHint()
                )
            }
            return PredicateResult(status: .fail, message: msg)
        }
        return PredicateResult(status: PredicateStatus(bool: matches), message: msg)
    }
}


public func equal<T, C: Equatable>(_ expectedValue: [T: C]?) -> Predicate<[T: C]> {
    return Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in
        let actualValue = try actualExpression.evaluate()
        switch (expectedValue, actualValue) {
        case (nil, _?):
            return PredicateResult(status: .fail, message: msg.appendedBeNilHint())
        case (nil, nil), (_, nil):
            return PredicateResult(status: .fail, message: msg)
        case (let expected?, let actual?):
            let matches = expected == actual
            return PredicateResult(bool: matches, message: msg)
        }
    }
}

