Last active
June 21, 2018 03:09
-
-
Save dpwright/6474401 to your computer and use it in GitHub Desktop.
Revisions
-
dpwright revised this gist
Sep 9, 2013 . 2 changed files with 43 additions and 33 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,39 @@ //maybe.h // //The Maybe type. //Provides a safer way to return possible failure than NULL values. Of course, //since C++ doesn't have pattern matching, it is down to you to ensure that you //always call isJust() to confirm there is a value available before calling //fromJust() to retrieve it. #pragma once #include <cassert> template<typename a> class Maybe { public: static const Maybe<a> Just(const a value) { return Maybe(value); } static const Maybe<a> Nothing() { return Maybe(); } const bool isJust() const { return m_valid; } const a fromJust() const { assert(isJust()); return m_value; } private: Maybe() : m_valid(false) {} Maybe(const a value) : m_value(value), m_valid(true) {} Maybe(const a value, const bool valid) : m_value(value), m_valid(valid) {} a m_value; const bool m_valid; }; template<typename a> const Maybe<a> Just(const a value) { return Maybe<a>::Just(value); } template<typename a> const Maybe<a> Nothing() { return Maybe<a>::Nothing(); } This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,42 +1,13 @@ //maybem.h // //The Maybe monad. //Adds monadic behaviour to Maybe. Allows you to sequence a number of //operations of type Maybe<a>, and drop out at the first point of failure. #pragma once #include "monad.h" #include "maybe.h" template<> struct Monad<Maybe> { -
dpwright revised this gist
Sep 9, 2013 . 1 changed file with 4 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -33,9 +33,9 @@ template<typename a> const Maybe<a> Just(const a value) return Maybe<a>::Just(value); } template<typename a> const Maybe<a> Nothing() { return Maybe<a>::Nothing(); } template<> struct Monad<Maybe> @@ -49,5 +49,6 @@ template<> struct Monad<Maybe> template<typename a, typename b> auto operator>>=(const Maybe<a>&& in, const b&& f) -> decltype(f(in.fromJust())) { typedef decltype(f(in.fromJust())) maybeType; return in.isJust() ? f(in.fromJust()) : maybeType::Nothing(); } -
dpwright revised this gist
Sep 9, 2013 . 2 changed files with 12 additions and 5 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -20,8 +20,6 @@ template<typename a> class Maybe const a fromJust() const { assert(isJust()); return m_value; } private: Maybe() : m_valid(false) {} Maybe(const a value) : m_value(value), m_valid(true) {} @@ -40,6 +38,14 @@ template<typename a> a Nothing() return a::Nothing(); } template<> struct Monad<Maybe> { template<typename a> static const Maybe<a> unit (a value) { return Just(value); } }; template<typename a, typename b> auto operator>>=(const Maybe<a>&& in, const b&& f) -> decltype(f(in.fromJust())) { This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,13 +1,14 @@ //monad.h // //Defines the two monad operations. Every class which wants to be treated as a //monad must provide a specialization for the Monad class or a constructor which //takes a single parameter of the type of the valuse it's wrapping. As well as //that, It must also overload operator>>= for binding purposes. #pragma once template <template <typename a, typename...> class m> struct Monad { template <typename a> static m<a> unit(a value) { return m<a>(value); } }; -
dpwright revised this gist
Sep 9, 2013 . 1 changed file with 0 additions and 5 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -8,13 +8,8 @@ #pragma once #include <cassert> template<typename a> class Maybe { public: -
dpwright revised this gist
Sep 9, 2013 . 4 changed files with 12 additions and 14 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -11,20 +11,18 @@ #include "monad.h" template<> struct Monad<std::list> { template<typename a> static const std::list<a> unit (a value) { return std::list<a>(1, value); } }; template<typename a, typename b> auto operator>>=(const std::list<a>& in, const b&& f) -> decltype(f(in.front())) { typedef typename std::remove_const<decltype(f(in.front()))>::type tmpList; tmpList out; for(auto i = in.begin(); i != in.end(); ++i) { This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -15,8 +15,6 @@ #include <functional> template<typename a> class Maybe { public: This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -7,6 +7,8 @@ #include "show.h" using namespace std; template<typename a> const Maybe<a> imSquare(a x) { return (abs(x) >= 0x8000) ? Maybe<a>::Nothing() : Maybe<a>::Just(x * x); } This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -16,22 +16,22 @@ template<typename t> std::string show(t x) template<typename a> std::string show(Maybe<a> x) { if(x.isJust()) { std::stringstream out; out << "Just " << x.fromJust(); return out.str(); } else return "Nothing"; } template<typename a, typename b> std::string show(std::pair<a, b> x) { std::stringstream out; out << "(" << x.first << "," << x.second << ")"; return out.str(); } template<typename a> std::string show(std::list<a> x) { std::stringstream out; out << "["; for(auto i = x.begin(); i != x.end(); ++i) { -
dpwright revised this gist
Sep 9, 2013 . 4 changed files with 32 additions and 39 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -9,7 +9,6 @@ #include <list> #include <type_traits> #include "monad.h" using namespace std; @@ -34,25 +33,3 @@ auto operator>>=(const list<a>& in, const b&& f) -> decltype(f(in.front())) } return out; } This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -15,8 +15,6 @@ #include <functional> using namespace std; template<typename a> class Maybe @@ -31,15 +29,6 @@ template<typename a> class Maybe static const Maybe<a> unit(a x) { return Maybe(x); } private: Maybe() : m_valid(false) {} Maybe(const a value) : m_value(value), m_valid(true) {} @@ -63,8 +52,3 @@ auto operator>>=(const Maybe<a>&& in, const b&& f) -> decltype(f(in.fromJust())) { return in.isJust() ? f(in.fromJust()) : Nothing<decltype(f(in.fromJust()))>(); } This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -5,6 +5,8 @@ #include "maybem.h" #include "listm.h" #include "show.h" template<typename a> const Maybe<a> imSquare(a x) { return (abs(x) >= 0x8000) ? Maybe<a>::Nothing() : Maybe<a>::Just(x * x); } This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -12,3 +12,33 @@ template<typename t> std::string show(t x) out << x; return out.str(); } template<typename a> std::string show(Maybe<a> x) { if(x.isJust()) { stringstream out; out << "Just " << x.fromJust(); return out.str(); } else return "Nothing"; } template<typename a, typename b> std::string show(pair<a, b> x) { stringstream out; out << "(" << x.first << "," << x.second << ")"; return out.str(); } template<typename a> std::string show(list<a> x) { stringstream out; out << "["; for(auto i = x.begin(); i != x.end(); ++i) { out << show(*i); if(i != --x.end()) out << ","; } out << "]"; return out.str(); } -
dpwright revised this gist
Sep 9, 2013 . 4 changed files with 102 additions and 7 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,9 +1,10 @@ # Monadic operations in C++ This began as a further attempt to implement the Maybe monad in C++, but quickly spiralled out of control and now includes an implementation of the List monad as well (using std::list!). This is really for my own amusement rather than to try and do anything useful with them. It also gave me an excuse to try out C++ 11 lambda functions for the first time. My original implementation defined a macro called `MBind` which caused a number of problems -- thankfully [PJayB][pjayb] managed to find a way around that so @@ -18,6 +19,6 @@ syntax on. In Haskell you'd probably use `do` syntax for a case like this, but I stuck with manually binding lambda functions so the similarity with the C++ is more obvious. Next up... The State monad! [pjayb]: https://gist.github.com/PJayB This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,58 @@ //listm.h // //The List monad. //Provide a way to build up lists over a sequence of operations. Adds monadic //functionality to std::list #pragma once #include <list> #include <type_traits> #include "show.h" #include "monad.h" using namespace std; template<> struct Monad<list> { template<typename a> static const list<a> unit (a value) { return list<a>(1, value); } }; template<typename a, typename b> auto operator>>=(const list<a>& in, const b&& f) -> decltype(f(in.front())) { typedef typename remove_const<decltype(f(in.front()))>::type tmpList; tmpList out; for(auto i = in.begin(); i != in.end(); ++i) { tmpList current = f(*i); out.splice(out.end(), current); } return out; } template<typename a, typename b> std::string show(pair<a, b> x) { stringstream out; out << "(" << x.first << "," << x.second << ")"; return out.str(); } template<typename a> std::string show(list<a> x) { stringstream out; out << "["; for(auto i = x.begin(); i != x.end(); ++i) { out << show(*i); if(i != --x.end()) out << ","; } out << "]"; return out.str(); } This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -3,6 +3,7 @@ #include "monad.h" #include "maybem.h" #include "listm.h" template<typename a> const Maybe<a> imSquare(a x) { return (abs(x) >= 0x8000) ? Maybe<a>::Nothing() : Maybe<a>::Just(x * x); @@ -17,9 +18,34 @@ const Maybe<int> testMaybe() return imSquare(c); };};}; } template<typename a, typename b> const list< pair<a, b> > cartesianProduct(const list<a> xs, const list<b> ys) { return xs >>= [&] (const a x) { return ys >>= [&] (const b y) { pair<a, b> product(x, y); return Monad<list>::unit(product); };}; } const list< pair<int, int> > testList() { static const int LIST_SIZE=5; list<int> xs_list; for(int i = 1; i <= LIST_SIZE; ++i) xs_list.push_back(i); list<int> ys_list; for(int i = 1; i <= LIST_SIZE; ++i) ys_list.push_back(i*i); return cartesianProduct(xs_list, ys_list); } int main(int argc, char** argv) { cout << show(testMaybe()) << endl; cout << show(testList()) << endl; return 0; } This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -8,4 +8,14 @@ testMaybe = return 0.5 >>= \d -> imSquare c cartesianProduct xs ys = xs >>= \x -> ys >>= \y -> return (x, y) testList = cartesianProduct xs ys where xs = [1..5] ys = map sq xs sq x = x * x main = print testMaybe >> print testList -
dpwright revised this gist
Sep 9, 2013 . 2 changed files with 11 additions and 9 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,11 +1,13 @@ //monad.h // //Defines the two monad operations. Every class which wants to be treated as a //monad must either provide a static function called "unit" or a specialization //for the Monad class, and must also overload operator>>= for binding purposes. #pragma once template <template <typename a, typename...> class m> struct Monad { template <typename a> static m<a> unit(a value) { return m<a>::unit(value); } }; This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -10,11 +10,11 @@ template<typename a> const Maybe<a> imSquare(a x) { const Maybe<int> testMaybe() { return Monad<Maybe>::unit(0x4000) >>= [&] (const int a) { return imSquare(a) >>= [&] (const int b) { int c = b / a; return Monad<Maybe>::unit(0.5f) >>= [&] (const float d) { return imSquare(c); };};}; } int main(int argc, char** argv) -
dpwright revised this gist
Sep 9, 2013 . 3 changed files with 22 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -15,6 +15,8 @@ #include <functional> #include "show.h" using namespace std; template<typename a> class Maybe @@ -61,3 +63,8 @@ auto operator>>=(const Maybe<a>&& in, const b&& f) -> decltype(f(in.fromJust())) { return in.isJust() ? f(in.fromJust()) : Nothing<decltype(f(in.fromJust()))>(); } template<typename a> std::string show(Maybe<a> x) { return x.show(); } This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -19,7 +19,7 @@ const Maybe<int> testMaybe() int main(int argc, char** argv) { cout << show(testMaybe()) << endl; return 0; } This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,14 @@ //show.h // //Defines the "show" operation. Defaults to using the stream operator. #pragma once #include <sstream> template<typename t> std::string show(t x) { std::stringstream out; out << x; return out.str(); } -
dpwright revised this gist
Sep 9, 2013 . 1 changed file with 0 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -6,8 +6,6 @@ #pragma once template<template <typename a> class m, typename a> const m<a> MUnit(a value) { return m<a>::unit(value); } -
dpwright revised this gist
Sep 8, 2013 . 1 changed file with 4 additions and 5 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -31,12 +31,11 @@ template<typename a> class Maybe std::string show() const { if(isJust()) { stringstream out; out << "Just " << fromJust(); return out.str(); } else return "Nothing"; } private: -
dpwright revised this gist
Sep 8, 2013 . 3 changed files with 9 additions and 25 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -5,23 +5,10 @@ monads in general, in C++. This is really for my own amusement rather than to try and do anything useful with them. It also gave me an excuse to try out C++ 11 lambda functions for the first time. My original implementation defined a macro called `MBind` which caused a number of problems -- thankfully [PJayB][pjayb] managed to find a way around that so this version uses C++ lambdas directly (take a look at the changelog if you want to see the changes made). Please bear in mind I made this purely out of curiosity -- I realise a lot of this is pathological in C++. @@ -32,3 +19,5 @@ I stuck with manually binding lambda functions so the similarity with the C++ is more obvious. Next up... The State and List monads! [pjayb]: https://gist.github.com/PJayB This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -3,11 +3,6 @@ //Defines the two monad operations. Every class which wants to be treated as a //monad must provide a static function called "unit", and must also overload //operator>>= for binding purposes. #pragma once This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -10,10 +10,10 @@ template<typename a> const Maybe<a> imSquare(a x) { const Maybe<int> testMaybe() { return MUnit<Maybe>(0x4000) >>= [&] (const int a) { return imSquare(a) >>= [&] (const int b) { int c = b / a; return MUnit<Maybe>(0.5f) >>= [&] (const float d) { return imSquare(c); };};}; } -
PJayB revised this gist
Sep 8, 2013 . 3 changed files with 7 additions and 11 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -52,14 +52,13 @@ template<typename a> const Maybe<a> Just(const a value) return Maybe<a>::Just(value); } template<typename a> a Nothing() { return a::Nothing(); } template<typename a, typename b> auto operator>>=(const Maybe<a>&& in, const b&& f) -> decltype(f(in.fromJust())) { return in.isJust() ? f(in.fromJust()) : Nothing<decltype(f(in.fromJust()))>(); } This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -13,9 +13,6 @@ #include <functional> template<template <typename a> class m, typename a> const m<a> MUnit(a value) { return m<a>::unit(value); } This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -10,10 +10,10 @@ template<typename a> const Maybe<a> imSquare(a x) { const Maybe<int> testMaybe() { return MUnit<Maybe>(0x4000) >>= [&] (const int a) -> const Maybe<int> { return imSquare(a) >>= [&] (const int b) -> const Maybe<int> { int c = b / a; return MUnit<Maybe>(0.5f) >>= [&] (const float d) -> const Maybe<int> { return imSquare(c); };};}; } -
dpwright created this gist
Sep 8, 2013 .There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,34 @@ # The Maybe monad in C++ A further attempt to implement the Maybe monad, and a framework for writing monads in general, in C++. This is really for my own amusement rather than to try and do anything useful with them. It also gave me an excuse to try out C++ 11 lambda functions for the first time. Issues with this version: * Portability -- it only compiles with clang++. g++ falls over trying to expand `MBind`, so you can get it compiling on g++ if you expand these yourself, but the syntax starts to look very painful then. * Verbosity -- C++ isn't as good at inferring types as Haskell, and in particular it can't dispatch based on the return type. The first parameter to `MBind` is a particular annoyance -- it always has to match the type of the final expression, which in turn has to match the type you're assigning to -- `result` in the case of `testMaybe`. So that's a lot of repetitive typing. * Incidentally, all `MBind` is actually doing is performing a typecast from a C++ lambda to a `std::function`, so that it can embed return type information. If we could just pass the lambda into the `operator>>=` function as-is we wouldn't need the `MBind` macro at all, and could instead just use the lambda, which has a lot of advantages including cleaner syntax and control over what we should include in the closure. * I had to use a `#define` for `MBind` :-( Please bear in mind I made this purely out of curiosity -- I realise a lot of this is pathological in C++. I've also included the equivalent Haskell code, so you can see what I based the syntax on. In Haskell you'd probably use `do` syntax for a case like this, but I stuck with manually binding lambda functions so the similarity with the C++ is more obvious. Next up... The State and List monads! This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,65 @@ //maybem.h // //The Maybe monad. //Provides a safer way to return possible failure than NULL values. Of course, //since C++ doesn't have pattern matching, it is down to you to ensure that you //always call isJust() to confirm there is a value available before calling //fromJust() to retrieve it. #pragma once #include <sstream> #include <string> #include <cassert> #include <functional> using namespace std; template<typename a> class Maybe { public: static const Maybe<a> Just(const a value) { return Maybe(value); } static const Maybe<a> Nothing() { return Maybe(); } const bool isJust() const { return m_valid; } const a fromJust() const { assert(isJust()); return m_value; } static const Maybe<a> unit(a x) { return Maybe(x); } std::string show() const { stringstream out; if(isJust()) out << "Just " << fromJust(); else out << "Nothing"; return out.str(); } private: Maybe() : m_valid(false) {} Maybe(const a value) : m_value(value), m_valid(true) {} Maybe(const a value, const bool valid) : m_value(value), m_valid(valid) {} a m_value; const bool m_valid; }; template<typename a> const Maybe<a> Just(const a value) { return Maybe<a>::Just(value); } template<typename a> const Maybe<a> Nothing() { return Maybe<a>::Nothing(); } template<typename a, typename b> const Maybe<b> operator>>=(const Maybe<a>&& in, function<const Maybe<b> (const a)> f) { return in.isJust() ? f(in.fromJust()) : Maybe<b>::Nothing(); } This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,21 @@ //monad.h // //Defines the two monad operations. Every class which wants to be treated as a //monad must provide a static function called "unit", and must also overload //operator>>= for binding purposes. // //I would have liked not to have had to resort to a #define for MBind, but //typing it in manually is pretty painful. In this case, it is operator>>= //which performs the binding operation itself; MBind is just a shortcut to hide //away C++'s hideous lambda syntax. #pragma once #include <functional> #define MBind(m, in_type, param_name) \ (function<const m (const in_type)>) [&] (const in_type param_name) template<template <typename a> class m, typename a> const m<a> MUnit(a value) { return m<a>::unit(value); } This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,25 @@ #include <iostream> #include <cmath> #include "monad.h" #include "maybem.h" template<typename a> const Maybe<a> imSquare(a x) { return (abs(x) >= 0x8000) ? Maybe<a>::Nothing() : Maybe<a>::Just(x * x); } const Maybe<int> testMaybe() { return MUnit<Maybe>(0x4000) >>= MBind(Maybe<int>, int, a) { return imSquare(a) >>= MBind(Maybe<int>, int, b) { int c = b / a; return MUnit<Maybe>(0.5f) >>= MBind(Maybe<int>, float, d) { return imSquare(c); };};}; } int main(int argc, char** argv) { cout << testMaybe().show() << endl; return 0; } This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,11 @@ imSquare x | abs x >= 0x8000 = Nothing | otherwise = Just (x * x) testMaybe = return 0x4000 >>= \a -> imSquare a >>= \b -> let c = b `div` a in return 0.5 >>= \d -> imSquare c main = print testMaybe