Monads/List monad: Difference between revisions

Content added Content deleted
m (→‎{{header|Phix}}: added syntax colouring the hard way)
(Added C++ implementation)
Line 141: Line 141:
{{Out}}
{{Out}}
<lang AppleScript>{{3, 4, 5}, {5, 12, 13}, {6, 8, 10}, {7, 24, 25}, {8, 15, 17}, {9, 12, 15}, {12, 16, 20}, {15, 20, 25}}</lang>
<lang AppleScript>{{3, 4, 5}, {5, 12, 13}, {6, 8, 10}, {7, 24, 25}, {8, 15, 17}, {9, 12, 15}, {12, 16, 20}, {15, 20, 25}}</lang>

=={{header|C++}}==
<lang cpp>#include <iostream>
#include <vector>

using namespace std;

// std::vector can be a list monad. Use the >> operator as the bind function
template <typename T>
auto operator>>(const vector<T>& monad, auto f)
{
// Declare a vector of the same type that the function f returns
vector<remove_reference_t<decltype(f(monad.front()).front())>> result;
for(auto& item : monad)
{
// Apply the function f to each item in the monad. f will return a
// new list monad containing 0 or more items.
const auto r = f(item);
// Concatenate the results of f with previous results
result.insert(result.end(), begin(r), end(r));
}
return result;
}

// The Pure function returns a vector containing one item, t
auto Pure(auto t)
{
return vector{t};
}

// A function to double items in the list monad
auto Double(int i)
{
return Pure(2 * i);
}

// A function to increment items
auto Increment(int i)
{
return Pure(i + 1);
}

// A function to convert items to a string
auto NiceNumber(int i)
{
return Pure(to_string(i) + " is a nice number\n");
}

// A function to map an item to a sequence ending at max value
// for example: 497 -> {497, 498, 499, 500}
auto UpperSequence = [](auto startingVal)
{
const int MaxValue = 500;
vector<decltype(startingVal)> sequence;
while(startingVal <= MaxValue)
sequence.push_back(startingVal++);
return sequence;
};

// Print contents of a vector
void PrintVector(const auto& vec)
{
cout << " ";
for(auto value : vec)
{
cout << value << " ";
}
cout << "\n";
}

// Print the Pythagorean triples
void PrintTriples(const auto& vec)
{
cout << "Pythagorean triples:\n";
for(auto it = vec.begin(); it != vec.end();)
{
auto x = *it++;
auto y = *it++;
auto z = *it++;
cout << x << ", " << y << ", " << z << "\n";
}
cout << "\n";
}

int main()
{
// Apply Increment, Double, and NiceNumber to {2, 3, 4} using the monadic bind
auto listMonad =
vector<int> {2, 3, 4} >>
Increment >>
Double >>
NiceNumber;
PrintVector(listMonad);
// Find Pythagorean triples using the list monad. The 'x' monad list goes
// from 1 to the max; the 'y' goes from the current 'x' to the max; and 'z'
// goes from the current 'y' to the max. The last bind returns the triplet
// if it is Pythagorean, otherwise it returns an empty list monad.
auto pythagoreanTriples = UpperSequence(1) >>
[](int x){return UpperSequence(x) >>
[x](int y){return UpperSequence(y) >>
[x, y](int z){return (x*x + y*y == z*z) ? vector{x, y, z} : vector<int>{};};};};
PrintTriples(pythagoreanTriples);
}
</lang>
{{out}}
<pre>
6 is a nice number
8 is a nice number
10 is a nice number
Pythagorean triples:
3, 4, 5
5, 12, 13
6, 8, 10
7, 24, 25
8, 15, 17
9, 12, 15
9, 40, 41
10, 24, 26
11, 60, 61
. . .
. . .
320, 336, 464
325, 360, 485
340, 357, 493
</pre>



=={{header|Clojure}}==
=={{header|Clojure}}==