Skip to content

nicuveo/CppTypeclasses

master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
 
 
 
 
 
 
 
 
 
 

C++ Typeclasses

Haskell's typeclasses are akin to what OO languages call interfaces, or even to abstract classes: they define a "contract", sometimes offer a default implementation, and even share some common vocabulary: a type that is an instance of a typeclass is said to be "deriving" it.

However, there's one big difference: one can implement a typeclass for an existing type without modifying it, while a class has to explicitly declare which interfaces it implements (except in Go, AFAIK).

This repository is an experiment: trying to come up with a working way to have Haskell-like typeclasses in C++. It... kinda works.

Of course, don't use that in real life.

Types

// "template <typename A>" omitted for readability

using Vec          = std::vector<A>;
using List         = std::list<A>;
using Map          = std::map<A, B>;
using Maybe        = boost::optional<A>;
using Either       = boost::variant<A, B>;
using Function     = std::function<B(A)>;
using Endomorphism = Function<A, A>;

typedef std::string String;

Either can't handle having the same type for A and B, due to the use of boost::variant.

Show

show :: a -> String

Works by default for any type that works with boost::lexical_cast. Implemented for all types except Function and Endomorphism.

Monoid

empty  :: a
append :: a -> a -> a
concat :: Container c => c a -> a

Implemented for Vec, List, Map, String, and Endomorphism. Containers accepted by concat are all standard containers that have a begin and an end method.

Functor

fmap :: (a -> b) -> f a -> f b

Implemented for all types except Endomorphism and String. Function composition is handled via std::bind.

Monad

mreturn :: a -> m a
(>>=)   :: m a -> (a -> m b) -> m b
(>>)    :: m a -> m b -> m b

Yes, both are valid and overloadable C++ operators. :)

However, (>>=) is right-associative, which means we have to add parens everywhere. And fail is yet to be implemented: I haven't yet found a proper way to specify a default implementation for one function only.

About

Haskell Typeclasses in C++

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages