Skip to content

Instantly share code, notes, and snippets.

@ostollmann
Last active August 29, 2015 14:06
Show Gist options
  • Save ostollmann/0c2d49cd060a8ef3de10 to your computer and use it in GitHub Desktop.
Save ostollmann/0c2d49cd060a8ef3de10 to your computer and use it in GitHub Desktop.

Revisions

  1. ostollmann revised this gist Sep 12, 2014. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion either.hxx
    Original file line number Diff line number Diff line change
    @@ -15,7 +15,7 @@ public:
    static either<L,R> right(R r) { return either(NULL,&r); }
    bool isLeft () const { return (_l != NULL); }
    bool isRight() const { return (_r != NULL); }
    L fromLeft () const { assert(isLeft()); return L(*_l); }
    L fromLeft () const { assert(isLeft ()); return L(*_l); }
    R fromRight () const { assert(isRight()); return R(*_r); }
    ~either() {
    if (_l != NULL) delete _l;
  2. ostollmann renamed this gist Sep 12, 2014. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  3. ostollmann renamed this gist Sep 12, 2014. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  4. ostollmann created this gist Sep 12, 2014.
    1 change: 1 addition & 0 deletions Run
    Original file line number Diff line number Diff line change
    @@ -0,0 +1 @@
    g++ -std=c++11 either.cxx; ./a.out
    24 changes: 24 additions & 0 deletions either.cxx
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,24 @@
    #include <iostream>
    #include <string>
    #include <functional>

    #include "either.hxx"

    using std::cout;
    using std::endl;

    using std::string;
    using std::function;

    int main() {
    function<either<string,int>(int)> f = [] (int x) {
    if (x == 2) { return either<string,int>::left("Cannot deal with 2."); }
    if (x == 12) { return either<string,int>::left("Cannot deal with 12."); }
    return either<string,int>::right(x*2);
    };
    cout << (((Return<string,int>(3) >>= f) >>= f) >>= f) << endl;
    // -> <Left:Cannot deal with 12.>
    cout << (((Return<string,int>(4) >>= f) >>= f) >>= f) << endl;
    // -> <Right:32>
    return 0;
    }
    54 changes: 54 additions & 0 deletions either.hxx
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,54 @@
    #ifndef _either_hxx_
    #define _either_hxx_

    #include <cassert>
    #include <ostream>
    #include <functional>

    using std::ostream;
    using std::function;

    template<class L,class R>
    class either {
    public:
    static either<L,R> left (L l) { return either(&l,NULL); }
    static either<L,R> right(R r) { return either(NULL,&r); }
    bool isLeft () const { return (_l != NULL); }
    bool isRight() const { return (_r != NULL); }
    L fromLeft () const { assert(isLeft()); return L(*_l); }
    R fromRight () const { assert(isRight()); return R(*_r); }
    ~either() {
    if (_l != NULL) delete _l;
    if (_r != NULL) delete _r;
    }
    private:
    L* _l; R* _r;
    either(const L* l,const R* r) : _l(l != NULL ? new L(*l) : NULL)
    , _r(r != NULL ? new R(*r) : NULL) {}
    };

    template<class L,class R>
    ostream& operator<<(ostream& out,const either<L,R> &e) {
    if (e.isLeft()) out << "<Left:" << e.fromLeft() << ">";
    if (e.isRight()) out << "<Right:" << e.fromRight() << ">";
    return out;
    }

    template<class L,class R1, class R2>
    either<L,R2> Bind(either<L,R1> e,function<either<L,R2>(R1)>& f) {
    if (e.isLeft()) return either<L,R2>::left(e.fromLeft());
    return f(e.fromRight());
    }

    template<class L,class R>
    either<L,R> Return(R r) {
    return either<L,R>::right(r);
    }

    template<class L,class R1,class R2>
    either<L,R2> operator>>=(either<L,R1>e,function<either<L,R2>(R1)>&f) {
    if (e.isLeft()) return either<L,R2>::left(e.fromLeft());
    return f(e.fromRight());
    }

    #endif