antmd
1/9/2011 - 1:48 PM

Example of lifting a monadic block into a function that operates on an NSArray

Example of lifting a monadic block into a function that operates on an NSArray

//
//  main.m
//  URLChanger
//  
//

#import <Foundation/Foundation.h>

typedef NSArray* (^LiftedFunctor)(id<NSFastEnumeration>) ;
typedef id (^Functor)(id);
    

LiftedFunctor lift(Functor functor);

// lift -- take a monadic functor and convert it to something that can operate on an array
LiftedFunctor lift(Functor functor)
{
    // TIP: omitting the return type means compiler infers it
    id liftedFunctor = ^ (id<NSFastEnumeration> fastEnumerable)
    {
        NSMutableArray* outArray = [ [ NSMutableArray alloc ] init ];
        for ( id item in fastEnumerable )
        {
            [outArray addObject:functor(item) ];
        }
        return [outArray autorelease];
    };

    // TIP: The copy-autorelease jazz is necessary to pluck the block off the stack, into the heap so we can pass it back
    return [ [ ((LiftedFunctor)liftedFunctor) copy ] autorelease ];
}


int main (int argc, const char * argv[]) {

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    
    
    NSArray* entries = [ NSArray arrayWithContentsOfFile:@"testmailboxes.plist" ]; 
    
    // TIP: using 'id' as the block literal type makes it easier to read. We need to cast to the block type before using it
    id printFunctor = ^ (id item)
    { 
        printf( "%s", (char*)[ [ NSString stringWithFormat:@"%@\n", (NSString*)item ] UTF8String ] );
        return [ NSNull null ]; // Our liftFunctor function requires something to push into it's result array
    };

    id liftedPrintFunctor = lift( printFunctor );

    ((LiftedFunctor)liftedPrintFunctor)(entries);


    [pool drain];
    return 0;
}