Jump to page: 1 2
Thread overview
Algebraic Data Types in D?
Jul 31, 2014
Remo
Jul 31, 2014
w0rp
Aug 01, 2014
Timon Gehr
Aug 01, 2014
bearophile
Aug 01, 2014
Timon Gehr
Aug 01, 2014
Timon Gehr
Jul 31, 2014
Wyatt
Jul 31, 2014
Sönke Ludwig
Jul 31, 2014
Justin Whear
Jul 31, 2014
bearophile
Jul 31, 2014
Remo
Jul 31, 2014
Meta
July 31, 2014
http://tech.esper.com/2014/07/30/algebraic-data-types/

D already has product type it is struct.
But D lacks sum type also called tagged-union.

Do you think it would be possible to add something like this to D2 ?
July 31, 2014
On Thursday, 31 July 2014 at 11:42:21 UTC, Remo wrote:
> http://tech.esper.com/2014/07/30/algebraic-data-types/
>
> D already has product type it is struct.
> But D lacks sum type also called tagged-union.
>
> Do you think it would be possible to add something like this to D2 ?

I think you're looking for std.variant?
http://dlang.org/phobos/std_variant.html

(My understanding is it's undergoing some heavy work, so do be aware of that.)

-Wyatt
July 31, 2014
On Thursday, 31 July 2014 at 11:42:21 UTC, Remo wrote:
> http://tech.esper.com/2014/07/30/algebraic-data-types/
>
> D already has product type it is struct.
> But D lacks sum type also called tagged-union.
>
> Do you think it would be possible to add something like this to D2 ?

There is a library solution for this in the standard library.

http://dlang.org/phobos/std_variant.html#.Algebraic

It doesn't handle recursive types at the moment, like alias Foo = Algebraic!(Foo[]). Apart from that, it should be what you are looking for.
July 31, 2014
Am 31.07.2014 13:42, schrieb Remo:
> http://tech.esper.com/2014/07/30/algebraic-data-types/
>
> D already has product type it is struct.
> But D lacks sum type also called tagged-union.
>
> Do you think it would be possible to add something like this to D2 ?

I'm currently in the process of polishing one up to improve vibe.d's Json/Bson type implementations. It's definitely possible to do (I've been using one for years), but has its caveats when there are dependency cycles in the code.

Just to make clear what the difference is:

 - "Variant": open set of types, using TypeInfo for identification
 - "Algebraic": closed set of types, using TypeInfo for identification
 - Tagged union: closed set of types with a numeric  ID for each type

The latter has a few advantages in some situations

 - Doesn't require type info
 - Can use "switch" instead of iterating over all possible types or storing a pointer to helper functions for dealing with the type
 - Allows to use "final switch" to guarantee handling all cases
 - Provides a handy type value that can be used and stored in user code (vs. passing and storing TypeInfo instances)
 - Could be made to store the same type with different IDs

July 31, 2014
On Thu, 31 Jul 2014 11:42:20 +0000, Remo wrote:

> http://tech.esper.com/2014/07/30/algebraic-data-types/
> 
> D already has product type it is struct.
> But D lacks sum type also called tagged-union.
> 
> Do you think it would be possible to add something like this to D2 ?

In addition to the suggestions of Algebraic or Variant elsewhere in this thread, it's trivial to implement your own concrete tagged unions:

struct MyTaggedUnion
{
   enum Type { Int, Float, String }
   Type tag;

   union {
      int int_;
      float float_;
      string string_;
   }
}

You can also hide the union members with private and only allow access via property getters that check the tag.
July 31, 2014
Justin Whear:

> In addition to the suggestions of Algebraic or Variant elsewhere in this
> thread, it's trivial to implement your own concrete tagged unions:
>
> struct MyTaggedUnion
> {
>    enum Type { Int, Float, String }
>    Type tag;
>
>    union {
>       int int_;
>       float float_;
>       string string_;
>    }
> }
>
> You can also hide the union members with private and only allow access
> via property getters that check the tag.

See for a bare-bones built-in pattern matching, with an optional "opMatch" struct method that gets called by the improved switch:
https://d.puremagic.com/issues/show_bug.cgi?id=596

Bye,
bearophile
July 31, 2014
On 7/31/14, 6:03 AM, w0rp wrote:
> On Thursday, 31 July 2014 at 11:42:21 UTC, Remo wrote:
>> http://tech.esper.com/2014/07/30/algebraic-data-types/
>>
>> D already has product type it is struct.
>> But D lacks sum type also called tagged-union.
>>
>> Do you think it would be possible to add something like this to D2 ?
>
> There is a library solution for this in the standard library.
>
> http://dlang.org/phobos/std_variant.html#.Algebraic
>
> It doesn't handle recursive types at the moment, like alias Foo =
> Algebraic!(Foo[]). Apart from that, it should be what you are looking for.

alias Foo = Algebraic!(This[]);

Andrei
July 31, 2014
On Thursday, 31 July 2014 at 15:03:09 UTC, Justin Whear wrote:
> On Thu, 31 Jul 2014 11:42:20 +0000, Remo wrote:
>
>> http://tech.esper.com/2014/07/30/algebraic-data-types/
>> 
>> D already has product type it is struct.
>> But D lacks sum type also called tagged-union.
>> 
>> Do you think it would be possible to add something like this to D2 ?
>
> In addition to the suggestions of Algebraic or Variant elsewhere in this
> thread, it's trivial to implement your own concrete tagged unions:
>
> struct MyTaggedUnion
> {
>    enum Type { Int, Float, String }
>    Type tag;
>
>    union {
>       int int_;
>       float float_;
>       string string_;
>    }
> }
>
> You can also hide the union members with private and only allow access
> via property getters that check the tag.

Thanks for all the answers !

> it's trivial to implement your own concrete tagged unions
Yes this is also possible to do in C++ too.
But I do not think that this is trivial at least not for 10 or 20 values.
Enum and Union need always to be in sync and compiler will not output error if the  programmer/user will make any mistake.

How to translate this useless Rust code to D, with as least D code as possible ?
How be sure that everything will still work as expected if programmer will add White color ?

  enum Color {
    Red,
    Green,
    Blue,
    Rgb(int,int,int)
  }

  fn main() {
    let r = Rgb(64,128,255);
    match r {
      Red   => println!("Red"),
      Green => println!("Green"),
      Blue  => println!("Blue"),
      Rgb(r,g,b)   => println!("Rgb({},{},{})",r,g,b),
    }
  }

July 31, 2014
On Thursday, 31 July 2014 at 20:28:55 UTC, Remo wrote:
> How to translate this useless Rust code to D, with as least D code as possible ?
> How be sure that everything will still work as expected if programmer will add White color ?
>
>   enum Color {
>     Red,
>     Green,
>     Blue,
>     Rgb(int,int,int)
>   }
>
>   fn main() {
>     let r = Rgb(64,128,255);
>     match r {
>       Red   => println!("Red"),
>       Green => println!("Green"),
>       Blue  => println!("Blue"),
>       Rgb(r,g,b)   => println!("Rgb({},{},{})",r,g,b),
>     }
>   }

import std.stdio;
import std.variant;

struct Red {}
struct Green{}
struct Blue {}
struct RGB
{
	int r;
	int g;
	int b;
}

alias Color = Algebraic!(Red, Green, Blue, RGB);

void main()
{
	auto r = Color(RGB(64, 128, 255));
	r.visit!(
		(Red   r) => writeln("Red"),
		(Green g) => writeln("Green"),
		(Blue  b) => writeln("Blue"),
		(RGB rgb) => writefln("RGB(%s, %s, %s)", rgb.r, rgb.g, rgb.b),
	);
}

D's Algebraic needs some work, but it's okay for basic usage. The most annoying thing is that you can't instantiate an RGB and expect the compiler to magically know that it's a subtype of Color. Maybe there's a way to work around that, but I can't think of one right off.
August 01, 2014
On 07/31/2014 06:23 PM, Andrei Alexandrescu wrote:
> On 7/31/14, 6:03 AM, w0rp wrote:
>> On Thursday, 31 July 2014 at 11:42:21 UTC, Remo wrote:
>>> http://tech.esper.com/2014/07/30/algebraic-data-types/
>>>
>>> D already has product type it is struct.
>>> But D lacks sum type also called tagged-union.
>>>
>>> Do you think it would be possible to add something like this to D2 ?
>>
>> There is a library solution for this in the standard library.
>>
>> http://dlang.org/phobos/std_variant.html#.Algebraic
>>
>> It doesn't handle recursive types at the moment, like alias Foo =
>> Algebraic!(Foo[]). Apart from that, it should be what you are looking
>> for.
>
> alias Foo = Algebraic!(This[]);
>
> Andrei

alias Foo = Algebraic!(int,Algebraic!(Foo[],double)[]);

There is also this kind of approach:

mixin ADT!q{
 List(T):
 | Nil
 | Cons T List!T
};


Of course, product types ("tuples") and sum types ("tagged unions") and recursive types are elementary enough to be proper language features in one way or another with all the syntactic convenience that yields for pattern matching.
« First   ‹ Prev
1 2