View mode: basic / threaded / horizontal-split · Log in · Help
October 06, 2008
Units of Measure in F#
I have found this interesting old thread, I don't know how much those things are true today too:
http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=36939

Beside allowing algebraic data types, that are quite useful, a functional-like type system allows to implement Units of Measure in a nice way:
http://blogs.msdn.com/andrewkennedy/archive/2008/08/20/units-of-measure-in-f-part-one-introducing-units.aspx

For people that don't remember what algebraic data types are:
http://en.wikipedia.org/wiki/Algebraic_data_type

This power also allows to use pattern matching, absent in Python, present in Haskell, Ocaml, Scala, etc.

Bye,
bearophile
October 06, 2008
Re: Units of Measure in F#
"bearophile" <bearophileHUGS@lycos.com> wrote in message 
news:gcdt5p$10t0$1@digitalmars.com...
>I have found this interesting old thread, I don't know how much those 
>things are true today too:
> http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=36939
>
> Beside allowing algebraic data types, that are quite useful, a 
> functional-like type system allows to implement Units of Measure in a nice 
> way:
> http://blogs.msdn.com/andrewkennedy/archive/2008/08/20/units-of-measure-in-f-part-one-introducing-units.aspx
>
> For people that don't remember what algebraic data types are:
> http://en.wikipedia.org/wiki/Algebraic_data_type
>
> This power also allows to use pattern matching, absent in Python, present 
> in Haskell, Ocaml, Scala, etc.
>
> Bye,
> bearophile

That's awesome. I want it!
October 06, 2008
Re: Units of Measure in F#
Reply to bearophile,

> I have found this interesting old thread, I don't know how much those
> things are true today too:
> http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmar
> s.D&article_id=36939
> 
> Beside allowing algebraic data types, that are quite useful, a
> functional-like type system allows to implement Units of Measure in a
> nice way:
> 
> http://blogs.msdn.com/andrewkennedy/archive/2008/08/20/units-of-measur
> e-in-f-part-one-introducing-units.aspx
> 
> For people that don't remember what algebraic data types are:
> http://en.wikipedia.org/wiki/Algebraic_data_type
> 
> This power also allows to use pattern matching, absent in Python,
> present in Haskell, Ocaml, Scala, etc.
> 
> Bye,
> bearophile

I think it is fully doable right now. I've considered doing it off and on 
for some time. I even figured out how to make it do rational powers for the 
dimensions.

The only thing I would want is to be able to avoid needing to wrap everything 
by way of operator overloads on typedefs

typedef real Unit(..stuff..)
{
  Unit!(stuff) opAdd(T)(T t) {...}
}

and some way to re-type functions

alias sqrt Unit!(stuff/2) sqrt(Unit!(stuff));  // if sqrt called with Unit!(stuff), 
return type is Unit!(stuff/2)
October 06, 2008
Re: Units of Measure in F#
On Tue, 07 Oct 2008 00:41:29 +0400, bearophile <bearophileHUGS@lycos.com>  
wrote:

> I have found this interesting old thread, I don't know how much those  
> things are true today too:
> http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=36939
>
> Beside allowing algebraic data types, that are quite useful, a  
> functional-like type system allows to implement Units of Measure in a  
> nice way:
> http://blogs.msdn.com/andrewkennedy/archive/2008/08/20/units-of-measure-in-f-part-one-introducing-units.aspx
>
> For people that don't remember what algebraic data types are:
> http://en.wikipedia.org/wiki/Algebraic_data_type
>
> This power also allows to use pattern matching, absent in Python,  
> present in Haskell, Ocaml, Scala, etc.
>
> Bye,
> bearophile

Arghh! I've almost done the trick with D templates and then I got this:
Assertion failure: 'i < parameters->dim' on line 784 in file 'template.c'

DMD is not ready for my funky templates yet! :)

I'll post my results (and a bug report) soon.
October 07, 2008
Re: Units of Measure in F#
Reply to Denis,

> On Tue, 07 Oct 2008 00:41:29 +0400, bearophile
> <bearophileHUGS@lycos.com>  wrote:
> 
>> I have found this interesting old thread, I don't know how much those
>> things are true today too:
>> http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalma
>> rs.D&article_id=36939
>> 
>> Beside allowing algebraic data types, that are quite useful, a
>> 
>> functional-like type system allows to implement Units of Measure in a
>> 
>> nice way:
>> 
>> http://blogs.msdn.com/andrewkennedy/archive/2008/08/20/units-of-measu
>> re-in-f-part-one-introducing-units.aspx
>> 
>> For people that don't remember what algebraic data types are:
>> http://en.wikipedia.org/wiki/Algebraic_data_type
>> 
>> This power also allows to use pattern matching, absent in Python,
>> present in Haskell, Ocaml, Scala, etc.
>> 
>> Bye,
>> bearophile
> Arghh! I've almost done the trick with D templates and then I got
> this: Assertion failure: 'i < parameters->dim' on line 784 in file
> 'template.c'
> 
> DMD is not ready for my funky templates yet! :)
> 
> I'll post my results (and a bug report) soon.
> 

svn.dsource.org  seems to be having problmes or I'd post a system I just 
put together.

total code, WS comments: ~ 400 LOC
supports 44 different units,
support +,-,* and / as well as pow and root
October 07, 2008
Re: Units of Measure in F#
Hmm... do we want to add pressure to energy density?
October 07, 2008
Re: Units of Measure in F#
BCS:
> svn.dsource.org  seems to be having problmes or I'd post a system I just 
> put together.
> total code, WS comments: ~ 400 LOC
> supports 44 different units,
> support +,-,* and / as well as pow and root

A lot of work. Does is use a (syntax) strategy similar to this?
http://www.boost.org/doc/libs/1_36_0/doc/html/boost_units.html

Now D just needs a pow infix operator (** ?) and that's done :-)

Bye,
bearophile
October 07, 2008
Re: Units of Measure in F#
Reply to bearophile,

> BCS:
> 
>> svn.dsource.org  seems to be having problmes or I'd post a system I
>> just
>> put together.
>> total code, WS comments: ~ 400 LOC
>> supports 44 different units,
>> support +,-,* and / as well as pow and root
> A lot of work. Does is use a (syntax) strategy similar to this?
> http://www.boost.org/doc/libs/1_36_0/doc/html/boost_units.html
> 
> Now D just needs a pow infix operator (** ?) and that's done :-)
> 
> Bye,
> bearophile

SVN is working again (or I'm somewhere it works from)

http://www.dsource.org/projects/scrapple/browser/trunk/units/

take a look at si.d first as it's the most useful intro (look way down at 
the bottom)
October 07, 2008
Re: Units of Measure in F#
BCS:
> take a look at si.d first as it's the most useful intro (look way down at 
> the bottom)

I think there's a need of some syntactic sugar :-)

Bye,
bearophile
October 07, 2008
Re: Units of Measure in F#
On Tue, 07 Oct 2008 22:39:10 +0400, BCS <ao@pathlink.com> wrote:

> Reply to bearophile,
>
>> BCS:
>>
>>> svn.dsource.org  seems to be having problmes or I'd post a system I
>>> just
>>> put together.
>>> total code, WS comments: ~ 400 LOC
>>> supports 44 different units,
>>> support +,-,* and / as well as pow and root
>> A lot of work. Does is use a (syntax) strategy similar to this?
>> http://www.boost.org/doc/libs/1_36_0/doc/html/boost_units.html
>>  Now D just needs a pow infix operator (** ?) and that's done :-)
>>  Bye,
>> bearophile
>
> SVN is working again (or I'm somewhere it works from)
>
> http://www.dsource.org/projects/scrapple/browser/trunk/units/
>
> take a look at si.d first as it's the most useful intro (look way down  
> at the bottom)
>
>

Well, I have done it completely different. Here is my (simplified) class  
hierarchy from memory:

// Unit is 's', 'kg', 'n' etc, i.e. they are basic orthogonal units
class Unit(string name)
{
    enum AsString = name;
}

// A Powered Unit :) PUnit is s^2, kg^(-3.14) etc.
// It is
class PUnit(Unit, float power)
{
    alias UnitType Unit;
    enum Power = power;
}

// Quantity consists of a unique set of PUnits and a value. It also
// defines a set of operations like opMul, opDiv, opAdd and opSub
// Example: 5 m/s^2
class Quantity(U...)
{
    alias Units U;

    private float value;

    // here is how my opMul looks like:
    Multiply!(Units, OtherUnits) opMul(OtherUnits)(OtherUnits other)
    {
        Multiply!(Units, OtherUnits) result = void;
        result.value = value * other.value;
        return result;
    }
}

here is how I merge Units for multiplication:

template GetUnitPower(Unit, Units...)
{
    static if (Units.length == 0) {
        enum GetUnitPower = 0;
    } else static if (is (Units[0].UnitType == Unit)) {
        enum GetUnitPower = Units[0].Power;
    } else {
        enum GetUnitPower = GetUnitPower!(Unit, Units[1..$]);
    }
}

template AddPowers(Unit, Units...)
{
    // GetUnitPower returns 0 if there is no such Unit in Units
    // put '-' for Divide! here
    enum Power = Unit.Power + GetUnitPower!(Unit.UnitType, Units);

    // get all the Units without Unit
    alias Without!(Unit.UnitType, Units) Rest;

    // Add the Unit with a new Power to the list of rest units
    alias Tuple!(PUnit!(Unit.UnitType, Power), Rest) Result;
}

As a result you can have any arbitrary amount of orthogonal Units. Add  
them with a single line:

mixin(defineUnit("Time", "s"));
mixin(defineUnit("Mass", "kg"));
mixin(defineUnit("Distance", "m"));
mixin(defineUnit("Speed", "m/s"));

Distance d = 6 * m;
Time t = 3 * s;
Speed s = d / t;
« First   ‹ Prev
1 2
Top | Discussion index | About this forum | D home