-
-
Save philsquared/1d267d823130eaf7641a to your computer and use it in GitHub Desktop.
A stab at a Result Monad (special case of Either monad) in Swift. Note that the Box helper is needed to workaround a compiler bug. Unfortunately this leaks into the usage quite considerably.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Box<T> { | |
let unbox: T | |
init(_ value: T) { self.unbox = value } | |
} | |
enum Result<T> { | |
case Ok(Box<T>) | |
case Fail(String) | |
init( ok value : T ) { self = .Ok( Box( value ) ) } | |
init( fail msg : String ) { self = .Fail( msg ) } | |
var isOk: Bool { | |
switch self { | |
case .Ok: return true | |
case .Fail: return false | |
} | |
} | |
} | |
postfix operator >! {} | |
postfix func >! <T>( value: Result<T> ) -> T { | |
switch value { | |
case .Ok( let boxedValue ): return boxedValue.unbox | |
case .Fail( let msg ): fatalError( msg ) | |
} | |
} | |
infix operator >>= { precedence 50 associativity left } | |
func >>= <T, U>( prevResult : Result<T>, nextFun : (T) -> Result<U> ) -> Result<U> { | |
switch prevResult { | |
case .Ok( let boxedValue ): return nextFun( boxedValue.unbox ) | |
case .Fail( let msg ): return .Fail(msg) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Use the >! operator like ! for Optionals to force unwrap the result (which throws a fatal error if it is not ok).
Use the >>= operator as a monadic bind to sequence blocks of code that deal with Result types (it adapts the result type of one call to the result type of the next, so the final type is what you get back - or an error).
Errors just have a string message. This could be an NSError, as others have done.