Skip to content

Instantly share code, notes, and snippets.

@cserb
Last active March 20, 2020 09:18
Show Gist options
  • Save cserb/fd71d148c9ba40192a2a57f312994367 to your computer and use it in GitHub Desktop.
Save cserb/fd71d148c9ba40192a2a57f312994367 to your computer and use it in GitHub Desktop.
Result Monad in Crystal Lang
enum Either
Ok
Err
end
struct Result(T)
getter value : T
getter type : Either
def initialize(@value, @type); end
def then(&block)
raise @value if @type.err?
yield @value
end
def then(ok : Proc, err : Proc)
return ok.call(@value) if @type.ok?
err.call(@value)
end
def self.ok(val : T)
Result(T).new(val, Either::Ok)
end
def self.err(val : T)
Result(T).new(val, Either::Err)
end
def ok? : Bool
@type.ok?
end
def err? : Bool
@type.err?
end
end
# FICTIONAL EXAMPLE
# assuming all methods return a Result(T)
create_from_string(str).then(
ok: ->(v : Foo){ validate_x(v) },
err: ->(e : Exception){ control_what_happens_on_error(e) }
).then { |v|
validate_y(v)
}.then { |v|
save(v)
}.then(
ok: ->(v : Foo) { http_client_post(v) },
err: ->(v : Exception) { maybe_even_revert_something_from_before(v) }
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment