MCPcopy Create free account
hub / github.com/BowenFu/hspp

github.com/BowenFu/hspp @0.0.1

Chat with this repo
repository ↗ · DeepWiki ↗ · release 0.0.1 ↗ · + Follow
961 symbols 1,437 edges 10 files 0 documented · 0% updated 3y ago0.0.1 · 2022-08-08★ 1714 open issues

Browse by type

Functions 456 Types & classes 505
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

hspp

hspp: bring Haskell Style Programming to C++.

Standard

Platform Platform Platform

CMake CMake GitHub license codecov

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

Here you are!

Sample 1 for monadic do notation

Filter even numbers.

Try it on godbolt

    using namespace hspp;
    using namespace hspp::doN;
    Id<int> i;
    auto const result = do_(
        i <= std::vector{1, 2, 3, 4},
        guard | (i % 2 == 0),
        return_ | i
    );

Sample 2 for monad comprehension

Obtain an infinite range of Pythagorean triples.

Haskell version

triangles = [(i, j, k) | k <- [1..], i <- [1..k], j <- [i..k] , i^2 + j^2 == k^2]

Try it on godbolt

    using namespace hspp::doN;
    using namespace hspp::data;
    Id<int> i, j, k;
    auto const rng = _(
        makeTuple<3> | i | j | k,
        k <= (enumFrom | 1),
        i <= (iota | 1 | k),
        j <= (iota | i | k),
        if_ || (i*i + j*j == k*k)
    );

Sample 3 for parser combinator

Original haskell version Monadic Parsing in 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 parse_expr

Try it on godbolt

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 <alt>
        do_(
            symb | "("s,
            n <= expr,
            symb | ")"s,
            return_ | n
        );

auto const term = factor <chainl1> mulOp;

TEParser<int> const expr = toTEParser || (term <chainl1> addOp);

Sample 4 for STM / concurrent

concurrent.cpp

Try it on godbolt

Transfer from one account to another one atomically.

Id<Account> from, to;
Id<Integer> v1, v2;
auto io_ = do_(
    from <= (newTVarIO | Integer{200}),
    to   <= (newTVarIO | Integer{100}),
    transfer | from | to | 50,
    v1 <= (showAccount | from),
    v2 <= (showAccount | to),
    hassert | (v1 == 150) | "v1 should be 150",
    hassert | (v2 == 150) | "v2 should be 150"
);
io_.run();

Withdraw from an account but waiting for sufficient money.

Id<Account> acc;
auto io_ = do_(
    acc <= (newTVarIO | Integer{100}),
    forkIO | (delayDeposit | acc | 1),
    putStr | "Trying to withdraw money...\n",
    atomically | (limitedWithdrawSTM | acc | 101),
    putStr | "Successful withdrawal!\n"
);

io_.run();

And we can also compose two STMs with orElse

// (limitedWithdraw2 acc1 acc2 amt) withdraws amt from acc1,
// if acc1 has enough money, otherwise from acc2.
// If neither has enough, it retries.
constexpr auto limitedWithdraw2 = toFunc<> | [](Account acc1, Account acc2, Integer amt)
{
    return orElse | (limitedWithdrawSTM | acc1 | amt) | (limitedWithdrawSTM | acc2 | amt);
};

Id<Account> acc1, acc2;
auto io_ = do_(
    acc1 <= (atomically | (newTVar | Integer{100})),
    acc2 <= (atomically | (newTVar | Integer{100})),
    showAcc | "Left pocket" | acc1,
    showAcc | "Right pocket" | acc2,
    forkIO | (delayDeposit | acc2 | 1),
    print | "Withdrawing $101 from either pocket...",
    atomically | (limitedWithdraw2 | acc1 | acc2 | Integer{101}),
    print | "Successful withdrawal!",
    showAcc | "Left pocket" | acc1,
    showAcc | "Right pocket" | acc2
);

io_.run();

Haskell vs Hspp (Incomplete list)

Haskell Hspp
function Function / GenericFunction
f x y f | x | y
f $ g x f || g | x
f . g $ x f \<o> g || x
a `f` b a \<f> b
[f x | x <- xs, p x] _(f | x, x <= xs, if_ || p | x)
list (lazy) range
list (strict) std::vector/list/forward_list
do {patA <- action1; action2} do_(patA <= action1, action2)
f <$> v f \<fmap> v
f <*> v f \<ap> v
pure a pure | a
m1 >> m2 m1 >> m2
m1 >>= f m1 >>= f
return a return_ | a

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.

Related

Haskell pattern matching is not covered in this repo. You may be interested in matchit(it) if you want to see how pattern matching works in C++.

Core symbols most depended-on inside this repo

Shape

Class 502
Method 340
Function 116
Enum 3

Languages

C++100%

Modules by API surface

include/hspp.h438 symbols
develop/include/typeclass.h200 symbols
develop/include/range.h137 symbols
develop/include/data.h71 symbols
include/concurrent.h62 symbols
develop/include/do_notation.h31 symbols
test/hspp/concurrent.cpp7 symbols
sample/parse_expr.cpp7 symbols
include/parser.h7 symbols
test/hspp/test.cpp1 symbols

For agents

$ claude mcp add hspp \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page