You might be interested by http://akabe.github.io/slap/ Thomas On 16 Oct 2014, at 17:37, Shayne Fletcher wrote: > Dear OCamlers, > > In 1994, Barton and Nackman in their book 'Scientific Engineering in > C++' [1] demonstrated how one could encode the rules of Dimensional > Analysis [2] into the C++ type system enabling compile-time checking > (no runtime-cost) of the plausibility (at least up to the dimensional > correctness) of computations. > > In 2004, Abrahams & Gurtovy in 'C++ Template Metaprogramming' [3] > showed the Barton Nackman technique to be elegantly implementable > using compile time type sequences encoding integer constants. At the > end of this post, I provide a complete listing of their example > program [4]. > > The key properties of the system (as I see it) are: > - Encoding of integers as types; > - Compile time manipulation of sequences of these integer encodings > to deduce/produce new derived types. > > Now, it is not immediately obvious to me how to approach this problem > in OCaml. It irks me some that I can't immediately produce a yet more > elegant OCaml program for this problem and leaves me feeling like C++ > has "got something over on us" here ;) > > My question therefore is: Does anyone have suggestions/pointers > on how to approach automatic dimensional analysis via the OCaml type > system? > > Best, > > -- > Shayne Fletcher > > [1] John J. Barton and Lee R. Nackman. Scientific and Engineering C++: > an Introduction with Advanced Techniques and Examples. Reading, > MA: Addison Wesley. ISBN 0-201-53393-6. 1994. > > [2] Wikipedia http://en.wikipedia.org/wiki/Dimensional_analysis > > [3] David Abrahams and Aleksey Gurtovy C++ Template Metaprogramming: > Concepts, Tools, and Techniques from Boost and Beyond (C++ in > Depth Series), Addison-Wesley Professional. ISBN:0321227255. 2004. > > [4] Code listing: > > //"c:/program files (x86)/Microsoft Visual Studio 10.0/vc/vcvarsall.bat" x64 > //cl /Fedimension.exe /EHsc /I d:/boost_1_55_0 dimension.cpp > > #include > #include > #include > #include > #include > #include > #include > > typedef boost::mpl::vector_c mass; > typedef boost::mpl::vector_c length; > typedef boost::mpl::vector_c time; > typedef boost::mpl::vector_c charge; > typedef boost::mpl::vector_c temperature; > typedef boost::mpl::vector_c intensity; > typedef boost::mpl::vector_c angle; > typedef boost::mpl::vector_c velocity; // l/t > typedef boost::mpl::vector_c acceleration; // l/(t2) > typedef boost::mpl::vector_c momentum; // ml/t > typedef boost::mpl::vector_c force; // ml/(t2) > typedef boost::mpl::vector_c scalar; > > template > class quantity > { > public: > explicit quantity (T val) > : val (val) > {} > template > quantity (quantity const& other) > : val (other.value ()) { > BOOST_MPL_ASSERT( (boost::mpl::equal)); > } > T value () const { return val; } > private: > T val; > }; > > template > quantity > operator + (quantity x, quantity y ) > { > return quantity(x.value () + y.value ()); > } > > template > quantity > operator - (quantity x, quantity y ) > { > return quantity(x.value () - y.value ()); > } > > template > quantity < > T > , typename boost::mpl::transform< > D1, D2, boost::mpl::plus< > boost::mpl::placeholders::_1 > , boost::mpl::placeholders::_2> >::type > > > operator* (quantity x, quantity y) > { > typedef typename boost::mpl::transform< > D1, D2, boost::mpl::plus< > boost::mpl::placeholders::_1 > , boost::mpl::placeholders::_2> >::type D; > > return quantity (x.value () * y.value ()); > } > > template > quantity < > T > , typename boost::mpl::transform< > D1, D2, boost::mpl::minus< > boost::mpl::placeholders::_1 > , boost::mpl::placeholders::_2> >::type > > > operator/ (quantity x, quantity y) > { > typedef typename boost::mpl::transform< > D1, D2, boost::mpl::minus< > boost::mpl::placeholders::_1 > , boost::mpl::placeholders::_2> >::type D; > > return quantity (x.value () / y.value ()); > } > > // -- test > > #include > #include > #include > > int main () > { > quantity m (5.0f); > quantity a(9.8f); > quantity f = m * a; > quantity m2 = f / a; > > assert ((std::abs ((m2 - m).value ())) <= std::numeric_limits::epsilon ()); > > return 0; > } >