Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save jonsterling/433497 to your computer and use it in GitHub Desktop.

Select an option

Save jonsterling/433497 to your computer and use it in GitHub Desktop.
- (void)saveManagedObjectContext {
id result = [[FKEither return:self.managedObjectContext] bind:^(id moc) {
NSError *err = nil;
[moc save:&err];
return [FKEither right:@"Success!" orLeft:err];
}];
NSLog(@"Saving managedObjectContext: %@", [result value]);
}
// hopefully => Saving managedObjectContext: Success!
// could also be => Saving managedObjectContext: OMG EPIC FAIL ASPLOSION
id justfine = [[FKEither return:@"dawg"] map:^id (id v) {
return [v substringToIndex:2];
}];
id willFail = [justfine map:^id (id v) {
return [v substringToIndex:120];
}];
NSLog(@"this is what success looks like: %@", [justfine value]);
NSLog(@"this is what failure looks like: %@", [willFail value]);
// => this is what success looks like: da
// => this is what failure looks like: *** -[NSCFString substringToIndex:]: Range or index out of bounds
// Most operations don't throw an exception, but write to an NSError reference.
// In these cases, we can use bind: instead of map:, and construct a
// new FKEither object on return from either the result of our operation,
// or the NSError object written to by its failure.
// This example shows how a failure looks, and also demonstrates the chaining
// of map operations after a bind. Note that further binds and maps on a value
// that is an error will do nothing. In that way, it is like the Maybe type.
id willFailBind = [[FKEither return:@""] bind:^(id s) {
NSError *err = nil;
NSString *f = [NSString stringWithContentsOfURL:[NSURL URLWithString:@"http://sdfsdf.com/fail.xml"]
encoding:NSUTF8StringEncoding
error:&err];
return [FKEither right:f orLeft:err];
}];
id willSucceedBind = [[[FKEither return:@""] bind:^(id s) {
NSError *err = nil;
NSString *f = [NSString stringWithContentsOfURL:[NSURL URLWithString:@"http://jonmsterling.com/index.html"]
encoding:NSUTF8StringEncoding
error:&err];
return [FKEither right:f orLeft:err];
}] map:^id(id s) {
return [s substringToIndex:15];
}];
NSLog(@"a binding failure: %@", [willFailBind value]);
NSLog(@"a binding success: %@", [willSucceedBind value]);
// => a binding failure: Error Domain=NSCocoaErrorDomain Code=256 "The operation couldn’t be completed. (Cocoa error 256.)" UserInfo=0x5c17aa0 {NSURL=http://sdfsdf.com/fail.xml}
// => a binding success: <!DOCTYPE html>

There are some problems

  • higher-order-messaging (as opposed to blocks) is still not working.
@jtbandes
Copy link

Are you using ...return:@""] bind:^(id s)... because that's your only Functor initializer? It doesn't look like you're using the encapsulated value.

@jonsterling
Copy link
Author

Yes and no. It's not a Functor initializer, but it is the only initializer I have at the moment. I plan to add the MonadPlus protocol, which declares things like mzero (an instance with no encapsulated value), which will simplify the syntax for operations like these.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment