March 04, 2017
Having taken a bit of time to get more familiar with Rust I wondered if we could have something like Rust's algebraic result type[1] using Phobos' Algebraic template and started to experiment:

--- Usage
enum DivisionError
{
    ZeroDivisor
}

Result!(int, DivisionError) divide(int dividend, int divisor)
{
    mixin Result;
    if (divisor == 0) { return err(DivisionError.ZeroDivisor); }
    return ok(dividend / divisor);
}


// If you statically know that in your specific case the error cannot
// happen you can just unwrap the Result to the contained successful value
int valid = divide(15, 3).unwrap();
// This will throw an instance of Error, since unwrapping a Result
// that you cannot guarantee to actually be Ok is a logic bug.
int invalid = divide(15, 0).unwrap();

// Do some calculations of which some may fail
auto input = [ tuple( 15, 3),
               tuple( -3, 0),
               tuple(  3, 7)];
auto results = input.map!(i => divide(i.expand));

// Use case 1: Silently ignore failed calculations
results.save
       .filter!(r => r.type == typeid(Ok!int))
       .each!(tryVisit!(
    (Ok!int result) => writeln(result),
    () {}
));

// Use case 2: "Handle" them
results.save
       .each!(Visit!(
    (Ok!int result) => writeln(result),
    (Err!DivisionError err) => writeln("Failed to divide: ", err)
));
---

--- Implementation
struct Ok(T) {
    T v;
    alias v this;
    string toString() { return v.to!string; }
}

struct Err(E) {
    E e;
    alias e this;
    string toString() { return e.to!string; }
}

alias Result(T, E) = Algebraic!(Ok!T, Err!E);

mixin template Result()
{
    alias R = typeof(return);
    alias T = typeof(__traits(getMember, R.AllowedTypes[0], "v"));
    alias E = typeof(__traits(getMember, R.AllowedTypes[1], "e"));

    R ok(T v) { return cast(R) Ok!T(v); }
    R err(E e) { return cast(R) Err!E(e); }
}

@trusted nothrow
auto unwrap(R)(R r)
{
    try {
        return cast(typeof(__traits(getMember, R.AllowedTypes[0], "v")))
               r.get!(R.AllowedTypes[0])();
    } catch (VariantException) {
        throw new Error("Attempted to unwrap error");
    } catch (Exception) {
        // VariantN.get is supposed to only throw VariantException. Bug?
        assert(false);
    }
}

import std.variant;
import std.conv;
import std.typecons;
import std.algorithm;
---

[1] https://doc.rust-lang.org/std/result/enum.Result.html