From aacfbfebde8e1ef82eea7a97f668774ba948200b Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Tue, 22 Jul 2014 13:49:15 -0400 Subject: [PATCH] Tutorial: write the preface, introduction and quick start --- README.md | 5 +- TUTORIAL.md | 35 ------- example/quickstart.cpp | 47 +++++++++ include/boost/hana.hpp | 192 ++++++++++++++++++++++++++++++++----- test/sandbox/worksheet.cpp | 4 +- 5 files changed, 218 insertions(+), 65 deletions(-) delete mode 100644 TUTORIAL.md create mode 100644 example/quickstart.cpp diff --git a/README.md b/README.md index 5a907b21e..92f6f27c0 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,8 @@ The library is unstable at the moment; do not use for production. ## Documentation -See the [TUTORIAL.md](TUTORIAL.md) file for the tutorial, and -http://ldionne.github.io/hana for the (mostly) up to date -reference documentation. +You can browse the documentation online at http://ldionne.github.io/hana. + ## Prerequisites and installation diff --git a/TUTORIAL.md b/TUTORIAL.md deleted file mode 100644 index 18b558c31..000000000 --- a/TUTORIAL.md +++ /dev/null @@ -1,35 +0,0 @@ -# Boost.Hana -> - - -## Table of contents -- [Preface](#preface) -- [Introduction](#introduction) -- [Quick start](#quick-start) -- [Organization](#organization) -- [Type classes](#type-classes) -- [Reference documentation](http://ldionne.github.io/hana) - - -## Preface - - - -## Introduction - - - -## Quick start - - - -## Organization - - - -## Type classes - - - - diff --git a/example/quickstart.cpp b/example/quickstart.cpp new file mode 100644 index 000000000..ab9abcd94 --- /dev/null +++ b/example/quickstart.cpp @@ -0,0 +1,47 @@ +/* +@copyright Louis Dionne 2014 +Distributed under the Boost Software License, Version 1.0. +(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + */ + +#include +#include +#include +#include +#include + +#include + +#include +using namespace boost::hana; + + +int main() { + // Value level programming + auto xs = list(1, '2', std::string{"345"}); + + assert(last(xs) == "345"); + assert(tail(xs) == list('2', std::string{"345"})); + BOOST_HANA_STATIC_ASSERT(!is_empty(xs)); + for_each(xs, [](auto x) { std::cout << x; }); + + auto to_xml = [](auto& ostream, auto xs) { + for_each(xs, [&](auto x) { + ostream << '<' << typeid(x).name() << '>' + << x + << "'; + }); + }; + to_xml(std::cout, xs); + + + // Type level programming + auto ts = list(type, type, type); + BOOST_HANA_STATIC_ASSERT(last(ts) == type); + BOOST_HANA_STATIC_ASSERT(fmap(metafunction, ts) == list(type, type, type)); + + static_assert(std::is_same< + decltype(last(ts))::type, + char const + >::value, ""); +} diff --git a/include/boost/hana.hpp b/include/boost/hana.hpp index d892c62ae..fdf15b588 100644 --- a/include/boost/hana.hpp +++ b/include/boost/hana.hpp @@ -45,6 +45,33 @@ Distributed under the Boost Software License, Version 1.0. #ifndef BOOST_HANA_HPP #define BOOST_HANA_HPP +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + //! @defgroup details Details //! Implementation details. @@ -87,31 +114,144 @@ Distributed under the Boost Software License, Version 1.0. //! @defgroup datatypes Data types //! General purpose data types provided by the library. -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +/*! +@mainpage Boost.Hana + +@tableofcontents + + +@section preface Preface + +The seed that became this library was planted in late 2012, when I first +started to reimplement the [Boost.MPL][] using C++11 in a project named +[MPL11][]. In spring 2014, I applied to [Google Summer of Code][GSoC] with +that project for the Boost organization and got in. The goal was to polish +the MPL11 and get it in Boost by the end of the summer. In May, before GSoC +was started full steam, I presented the project at [C++Now][] and had +insightful conversations with several attendees. The idea that it was +possible to unify the [Boost.Fusion][] and the [Boost.MPL][] libraries +made its way and I became convinced of it after writing the first prototype +for what is now Boost.Hana. We are now in late July and the plan is to +request an official review to get the library in Boost by the end of GSoC; +we'll see how that works out. + +Let the fun begin. + + +@section introduction Introduction + +Boost.Hana is a library of combinators tailored towards the manipulation of +heterogeneous collections. However, the core of Hana is a powerful system for +ad-hoc polymorphism inspired by Haskell type classes; this extension system +is then used to provide all the functionality of the library in a generic way. + +The library uses a purely functional style of programming, which is required +to manipulate objects of heterogeneous types -- it is impossible to modify the +type of an object, so a new object must be introduced. + +Contrary to previous metaprogramming libraries like Boost.MPL and Boost.Fusion, +the design of the library is not based on that of the STL. Rather, it is +strongly inspired by several (standard and non standard) modules written for +the Haskell programming language. Through experience, the author has found +this to be much more expressive, flexible and easy to use while not sacrificing +any performance given the purely functional setting. + + +@section quick-start Quick start + +This section assumes the reader is already familiar with `std::tuple` and +basic metaprogramming. First, let's include the library: + +@dontinclude example/quickstart.cpp +@skip boost/hana.hpp +@until using namespace + +> #### Note +> Unless specified otherwise, the documentation assumes that the above lines +> are present before examples and code snippets. Use your judgement! + +Finer grained headers are provided and will be explained in the +@ref organization section, but for now this will do. Let's create an +heterogeneous list, which is conceptually the same as a `std::tuple`: + +@skipline auto xs = + +Here, `list` is a generic lambda taking a variable number of arguments and +returning an object which is a valid sequence for Boost.Hana. The actual type +of the object returned by `list` is left unspecified, as will always be the +case in this library. However, something called its "data type" is specified; +`list` returns an object of data type `List`. Data types will be explained in +detail in their own section. There are several operations that can be performed +on lists; here are a couple so you get the feeling: + +@skip assert +@until for_each + +An interesting observation is that `is_empty` returns a value that can be +constexpr-converted to bool even though the list contains non-constexpr +objects (a `std::string`). Indeed, the size of the sequence is known at +compile-time regardless of its content, so it only makes sense that the +library does not throw away this information. Let's take that `for_each` +for a tour and write a function that prints a list as XML: + +@skip auto to_xml = +@until to_xml( + +One of the initial goals of the library was to unify type level programming +with value level programming. So in principle, it should be possible to +manipulate types and sequences of types just as one would do with the +Boost.MPL. Here is how Hana does it: + +@skip auto ts = +@until fmap + +There is a lot going on here. First, `type` is a variable template, and +`type` is an object representing the C++ type `T`. Since it's an object, +it makes perfect sense to create a list out of these guys. Second, `fmap` is +a function similar to `std::transform`: it takes a function object and a list +(actually any `Functor` -- more on this later), applies the function to every +element in the list and returns the resulting list. Now, this means that +somehow `metafunction` is in fact a function object. +Specifically, `metafunction` is a variable template taking a template +template parameter, and `metafunction` is a function +object which accepts a `type` and returns `type::%type>`. +Still with me? + +So far, we can perform computations on C++ types but we can't really do +anything useful with the result if we can't get the type out, i.e. get the +`T` out of `type`. This is easily done: + +@skip static_assert +@until >::value + +It turns out that while `type` has an unspecified C++ type, that C++ type +is still guaranteed to have a nested type named `type` which is an alias to +`T`. In Boost.MPL parlance, `decltype(type)` is a nullary metafunction +returning `T`. + +This is it for the quick start. Of course, there is much more available like +associative sequences, sets, ranges and even an heterogeneous `std::optional` +called `Maybe`, but you can read on if you want to know more. + + +@section organization Organization + + + +@section datatypes Data types + + +@section type-classes Type classes + + + + +[Boost.Fusion]: http://www.boost.org/doc/libs/release/libs/fusion/doc/html/index.html +[Boost.MPL]: http://www.boost.org/doc/libs/release/libs/mpl/doc/index.html +[C++Now]: http://cppnow.org +[GSoC]: http://www.google-melange.com/gsoc/homepage/google/gsoc2014 +[MPL11]: http://github.com/ldionne/mpl11 + + */ #endif // !BOOST_HANA_HPP diff --git a/test/sandbox/worksheet.cpp b/test/sandbox/worksheet.cpp index 0131d9fc3..f6baab905 100644 --- a/test/sandbox/worksheet.cpp +++ b/test/sandbox/worksheet.cpp @@ -8,6 +8,8 @@ Distributed under the Boost Software License, Version 1.0. */ - +#include +using z = std::add_pointer_t; +static_assert(std::is_same{}, ""); int main() { }