Skip to content

Commit

Permalink
Readme. (#16)
Browse files Browse the repository at this point in the history
* Fix.

* Fix.

* Fix.

* README.

* README.

Co-authored-by: Bowen Fu <missing>
  • Loading branch information
BowenFu authored Jun 25, 2022
1 parent 9937a34 commit b736a46
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 20 deletions.
64 changes: 60 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@

hspp: Haskell Style Programming brought to Cpp.

Mom, can we have monadic do notation / monad comprehension in C++?

Here you are!

![Standard](https://img.shields.io/badge/c%2B%2B-17/20-blue.svg)

![Platform](https://img.shields.io/badge/platform-linux-blue)
Expand All @@ -17,6 +13,11 @@ Here you are!
![GitHub license](https://img.shields.io/github/license/BowenFu/hspp.svg)
[![codecov](https://codecov.io/gh/BowenFu/hspp/branch/main/graph/badge.svg)](https://codecov.io/gh/BowenFu/hspp)


## Mom, can we have monadic do notation / monad comprehension in C++?

Here you are!

Sample 1

```c++
Expand Down Expand Up @@ -44,3 +45,58 @@ Sample 2
return_ | i
);
```

Sample 3 (Parser Combinator)

Original haskell version (Monadic Parsing in Haskell)

```haskell
expr, term, factor, digit :: Parser Int

digit = do {x <- token (sat isDigit); return (ord x - ord '0')}

factor = digit +++ do {symb "("; n <- expr; symbol ")"; return n}

term = factor `chainl1` mulop

expr = term `chainl1` addop
```

C++ version

```c++
Id<char> x;
auto const digit = do_(
x <= (token || sat | isDigit),
return_ | (x - '0')
);

extern TEParser<int> const expr;

Id<int> n;
auto const factor =
digit <triPlus>
do_(
symb | "("s,
n <= expr,
symb | ")"s,
return_ | n
);

auto const term = factor <chainl1> mulOp;

extern TEParser<int> const expr = toTEParser || (term <chainl1> addOp);
```
## Why bother?
The library is
1. for fun,
2. to explore the interesting features of Haskell,
3. to explore the boundary of C++,
4. to facilitate the translation of some interesting Haskell codes to C++.
This library is still in active development and not production ready.
Discussions / issues / PRs are welcome.
8 changes: 5 additions & 3 deletions include/hspp.h
Original file line number Diff line number Diff line change
Expand Up @@ -2730,6 +2730,7 @@ BIN_OP_FOR_NULLARY(==)
BIN_OP_FOR_NULLARY(%)
BIN_OP_FOR_NULLARY(<)
BIN_OP_FOR_NULLARY(&&)
BIN_OP_FOR_NULLARY(-)

template <typename T, typename BodyBaker>
constexpr auto funcWithParams(Id<T> const& param, BodyBaker const& bodyBaker)
Expand All @@ -2755,10 +2756,11 @@ constexpr auto doImplNullaryDeMonad(Nullary<N> const& dmN, Rest const&... rest)
return doImpl<MClass>(dmN(), rest...);
}

template <typename MClass, typename... Rest>
constexpr auto doImpl(DeMonad<MClass> const& dm, Rest const&... rest)
template <typename MClass1, typename MClass2, typename... Rest>
constexpr auto doImpl(DeMonad<MClass2> const& dm, Rest const&... rest)
{
auto const bodyBaker = [=] { return doImpl<MClass>(rest...);};
static_assert(std::is_same_v<MonadType<MClass1>, MonadType<MClass2>>);
auto const bodyBaker = [=] { return doImpl<MClass2>(rest...);};
return dm.m() >>= funcWithParams(dm.id(), bodyBaker);
}

Expand Down
32 changes: 19 additions & 13 deletions sample/parseExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@ auto expectEq(T const& l, T const& r)
}
}

using namespace hspp::parser;
using namespace hspp;
using namespace hspp::parser;
using namespace hspp::doN;
using namespace std::literals;


enum class Op
{
Expand Down Expand Up @@ -64,8 +67,8 @@ static_assert((sub | 1 | 2) == -1);
static_assert((mul | 1 | 2) == 2);
static_assert((div | 4 | 2) == 2);

auto const addOp = ((symb | "+") >> (return_ | add)) <triPlus> ((symb | "-") >> (return_ | sub));
auto const mulOp = ((symb | "*") >> (return_ | mul)) <triPlus> ((symb | "/") >> (return_ | div));
auto const addOp = do_(symb | "+", return_ | add) <triPlus> do_(symb | "-", return_ | sub);
auto const mulOp = do_(symb | "*", return_ | mul) <triPlus> do_(symb | "/", return_ | div);
} // namespace op

using op::addOp;
Expand All @@ -76,20 +79,23 @@ constexpr auto isDigit = toFunc<> | [](char x)
return isdigit(x);
};

extern TEParser<int> const expr;
Id<char> x;
auto const digit = do_(
x <= (token || sat | isDigit),
return_ | (x - '0')
);

auto const digit = (token || sat | isDigit)
>>= [](char x) { return
return_ | (x - '0');
};
extern TEParser<int> const expr;

using namespace std::literals;
Id<int> n;
auto const factor =
digit <triPlus>
(((symb | "("s) >> expr) >>= [](auto n){ return
(symb | ")"s) >>
(return_ | n);
});
do_(
symb | "("s,
n <= expr,
symb | ")"s,
return_ | n
);

auto const term = factor <chainl1> mulOp;

Expand Down

0 comments on commit b736a46

Please sign in to comment.