Skip to content
Go to file

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time


A simple Maybe monad implementation in Objective-C.

Why Bother?

If you already know about Maybe from languages like Haskell, and you're familiar with Objective-C, you may be asking: "Why bother?" In Objective-C, sending a message to nil returns nil, so with a category on NSObject that adds a binding method like ifNotNil or Haskell's >>= operator, we already have Maybe monad functionality. Nothing more is necessary. But if we want more sophisticated binding functionality like that described below, this won't suffice. In that case, we need a "smarter" nil, which is what SVMaybe provides.


SVMaybe provides the following:

  1. An elegant solution to the common problem of nested nil checks in Objective-C code.
  2. Custom definitions of what is meant by "nothing" on a per-class basis ("semantic nil").

If you've ever found yourself writing something tedious like this:

NSDictionary *person = @{@"name":@"Homer Simpson", @"address":@{@"street":@"123 Fake St", @"city":@"Springfield"}};
NSString *cityString;

if (person)
    NSDictionary *address = (NSDictionary *)[person objectForKey:@"address"];
    if (address)
        NSString *city = (NSString *)[address objectForKey:@"city"];
        if (city)
            cityString = city;
            cityString = @"No city."
        cityString = @"No address.";
    cityString = @"No person.";

SVMaybe allows you to more concisely and declaratively provide the same solution:

NSDictionary *person = @{@"name":@"Homer Simpson", @"address":@{@"street":@"123 Fake St", @"city":@"Springfield"}};
NSString *cityString = [[[Maybe(person) whenNothing:Maybe(@"No person.") else:MapMaybe(person, [person objectForKey:@"address"])]
                                        whenNothing:Maybe(@"No address.")] else:MapMaybe(address, [address objectForKey:@"city"])]
                                        whenNothing:Maybe(@"No city.")] justValue];

It also allows you to move beyond simple nil checks by offering run-time redefinition of what is meant by "nothing" on a per-class basis. For instance, in the above example suppose that empty strings should also be considered "nothing." Here's the re-definition:

[NSString defineNothing:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
    return [(NSString *)evaluatedObject length] == 0;

Given this re-definition, if any of the strings in the above example were empty (or nil), the monad binding would short to nothing and return the appropriate default string wrapped in a SVMaybe.

Creating Maybes

Use the provided macros:

Maybe(nil); // Equals Nothing

Or a static method:

[SVMaybe maybe:@"foo"];
[SVMaybe maybe:nil]; // Equals [SVMaybe nothing]
[SVMaybe nothing];

Getting Values

To get the value of a maybe:

[Maybe(@"foo") justValue] // "foo"
[Nothing justValue] // Throws an exception!

Binding and Chaining

SVMaybe offers a few other chaining options in addition to whenNothing:else described above:

  • andMaybe: Binds multiple maybe values together, returning the last bound maybe. If any maybe is "nothing," the binding shorts and returns "nothing." (Equivalent to >> in Haskell.)

  • whenSomething: Binds and maps multiple maybes together using the provided block. If any maybe is "nothing," the binding shorts and returns "nothing." (Equivalent to >>= in Haskell.)

  • whenNothing: Same as whenNothing:else: but without the else block. Returns self if not nothing.


A Maybe monad implementation for Objective-C




No releases published


No packages published
You can’t perform that action at this time.