# Sum algebraic data type #258

Merged
merged 10 commits into from May 7, 2015

## Conversation

Projects
None yet
4 participants
Contributor

### yloiseau commented Apr 6, 2015

This PR adds sum algebraic data types, also known as tagged union, to Golo
(see http://en.wikipedia.org/wiki/Tagged_union).
Product data types are already provided by `struct` and `tuple`.

## Usage example

Some well known usages of sum types are:

### Enumerations

```union Color = {
RED
GREEN
BLUE
}```

It is here somewhat equivalent to Java `enum`, and can be extended through
augmentation.

### Option type

```union Option = {
Some = {value}
None
}```

Values can have fields. They are in this respect similar to `struct`

### Lists

```union ConsList = {
List = { head, tail }
Empty
}```

### Binary trees

```union Tree = {
Empty
Leaf = { value }
Node = { left, right }
}```

## Augmentations

The `union` itself is a abstract class, and each possible value is a concrete
final (inner) class extending it. It is thus possible to augment the whole `union`:

```augment Option {
function map = |this, func| -> match {
when this == Option.None() then this
otherwise Option.Some(func(this: value()))
}
}```

or just a value:

```augment ConsList\$Empty {
function isEmpty = |this| -> true
function head = |this| -> null
function tail = |this| -> this
}
augment ConsList\$List {
function isEmpty = |this| -> false
}```

## Remark

I want to provide a neat namespace for the generated classes, to allow the
definition of unions with values having the same name in the same module.

Currently, the union itself is an abstract class and each value is an inner
class of the union. The FQN of a value type is thus `module.types.MyUnion\$Value`.
The abstract class provides static factory methods to create the values, used
as `MyUnion.Value(fields...)`

As an example, a `union` declaration like:

```union Option = {
Some = { value }
None
}```

generates classes equivalents to:

```abstract class Option {

public static final class Some extends Option {
public final Object value;
protected Some(Object v) { this.value = v; }

@Override
public String toString() {
return "enum Option.Some{value=" + value + "}";
}

@Override
public boolean equals(Object other) {
if (other == this) { return true; }
if (other == null) { return false; }
if (!(other instanceof Some)) { return false; }
Some o = (Some) other;
return java.util.Objects.equals(value, o.value);
}

@Override
public int hashCode() {
return java.util.Objects.hash(value);
}
}

public static Option Some(Object value) {
return new Some(value);
}

public static final class None extends Option {
@Override
public String toString() {
return "enum Option.None";
}
}

public static final Option None = new None();

}```

An other solution is to use public classes in a sub-package, giving types like
`module.types.myunion.Value` and to generate factory functions in the defining
module (as it is the case for `struct`)

I'm not sure what is the more convenient. What do you think?

Contributor

### yloiseau commented Apr 6, 2015

 Comments on syntax and implementation are welcome
Member

### jponge commented Apr 6, 2015

 Waoo... I'll have a look tomorrow but it looks like you have done something terrific :-)
Contributor

### yloiseau commented Apr 6, 2015

 to be done: tests... (I known, TDD next time) golodoc integration syntax highlighting a golo library of useful unions ?
Contributor

### danielpetisme commented Apr 6, 2015

 How do you do that.... every you touch is automatically converted into a mathematical concept ! 😉 Hats off
Contributor

### yloiseau commented Apr 6, 2015

 @danielpetisme functional programming power! ✌️
Contributor

### yloiseau commented Apr 7, 2015

 BTW, I’m not sure about the keyword name, which could be misleading. Possibilities could be: `enum` : used in Rust and Swift, hence my choice `union` (unions in C are somewhat similar) `variant` : used in Boost lib and D `sum` (also misleading) `sumType` Any toughts?
Contributor

### danielpetisme commented Apr 7, 2015

 I vote for `enum` (my first thought is java enum but If I'm right is not excatly the same) `variant` (cause it's a new keyword in my Java world so it force me to open some docs to understand the concept) Otherwise I could invent a term (I miss `pimp` 😉 )
Member

### jponge commented Apr 7, 2015

 `enum` looks good to me. `union`, too.

### jponge reviewed Apr 7, 2015

 Some well known usages of sum types are: ==== Enumerations

#### jponge Apr 7, 2015

Member

I think you can go for a consistent header style rather than sometimes `== foo ==` and sometimes `== foo` 😃

#### jponge Apr 7, 2015

Member

BTW `== title` is more idiomatic asciidoc.

#### yloiseau Apr 7, 2015

Contributor

the current golo documentation mainly use `== title ==` 😉

#### jponge Apr 7, 2015

Member

Le 7 avr. 2015 à 19:16, Yannick Loiseau notifications@github.com a écrit :

In doc/enums.asciidoc:

+}
+
+function main = |args| {

• let aString = Option.Some("Hello")
• println(aString: value())
• let noString = Option.None()
• println(noString)
+}
+----

+=== Usage example ===
+
+Some well known usages of sum types are:
+
+==== Enumerations
the current golo documentation mainly use == title ==

Reply to this email directly or view it on GitHub.

### jponge reviewed Apr 7, 2015

 otherwise func(this: value()) } function fmap = |this, func| -> match {

#### jponge Apr 7, 2015

Member

`flatMap`

#### yloiseau Apr 7, 2015

Contributor

To match `java.util.Optional`, `bind` should be `flatMap` and `fmap` should be `map`. I used here the classical monad vocabulary, but I can switch to Java if you prefer

Member

### jponge reviewed Apr 7, 2015

 mv.visitVarInsn(ASTORE, 2); // java.util.Objects.equals(, other.) for (String member : value.getMembers()) {

#### jponge Apr 7, 2015

Member

Isn't `Objects.equals(...)` already doing the above checks?

#### yloiseau Apr 7, 2015

Contributor

`Objects.equals` is used here to compare the members, while the checks above tests for the instance itself

Member

### jponge reviewed Apr 7, 2015

 @@ -78,6 +85,14 @@ public String toJVMType() { return toString().replaceAll("\\.", "/"); } /** * @return a JVM reference type representation for this object, e.g.: foo.Bar gives

#### jponge Apr 7, 2015

Member

I'd rather use `{@code }` blocks in Javadocs.

#### yloiseau Apr 7, 2015

Contributor

copy-pasted from above 😄

Member
Member

### jponge commented Apr 7, 2015

 That's a lovely pull request 👏
Contributor

### danielpetisme commented Apr 7, 2015

 Could it be a good practice to separate all the bytecode generation in dedicated classes? Just as you did w/ `JavaBytecodeEnumGenerator`. Currently the class JavaBytecodeGenerationGoloIrVisitor looks like the almighty God of Bytecode generation (up to 800 LoC). Thoughts?
Member

### jponge commented Apr 7, 2015

 It is not necessarily very easy to split `JavaBytecodeGenerationGoloIrVisitor`. We already have a class for structs bytecode generation. It's big, but quite readable and methods aren't too fat :-)
Contributor

### yloiseau commented Apr 7, 2015

 @jponge thanks, it was fun to do... @danielpetisme I just mimic the `struct` implementation, without considering refactoring. As @jponge said, the split is not easy since the visitor keeps a global state if I recall correctly.
Contributor

### artpej commented Apr 8, 2015

 I prefer `union` to keep a certain consitency with `struct` and to be less confusing with java `enums`.
Contributor

### yloiseau commented Apr 8, 2015

 I think I'm gonna rename all stufs as `union`, to be more clear that it’s more than an equivalent of java `enum`
Member

### jponge commented Apr 8, 2015

 I like `union` 👍
Contributor

### yloiseau commented May 7, 2015

 I think this PR is ready (since highlighting is elsewhere and a lib of useful unions can be done in an other PR). Any other comments?

### jponge reviewed May 7, 2015

 Golo allows the definition of sum algebraic data types, also known as _tagged_union_ footnote:[ http://en.wikipedia.org/wiki/Tagged_union[Wikipedia: Tagged union]

Member

#### yloiseau May 7, 2015

Contributor

I have used footnotes everywhere in the doc I wrote (augmentations, decorators)... I'll review that and change to simple links

### jponge reviewed May 7, 2015

 === Usage example Some well known usages of sum types are:

#### jponge May 7, 2015

Member

I'd suggest

Some well known usages of sum types are the following.

### jponge reviewed May 7, 2015

 === JVM existence An `union` type is compiled to an abstract JVM class. Each alternative value

#### jponge May 7, 2015

Member

A union type, not an :-)

Member

### jponge commented May 7, 2015

 Minor comments on the documentation. Otherwise this is a huge feature, hats-off 😄

Member

### jponge commented May 7, 2015

 @yloiseau You can merge at your convenience.

### yloiseau added some commits Apr 5, 2015

``` Adds sum algebraic data types. ```
``` 6ccf8ad ```
``` Adds a section to the doc about enum type. ```
``` 995d7fb ```

### yloiseau added some commits Apr 6, 2015

``` Adds a sample file for enum ```
``` b204e85 ```
``` Minor fixes. ```
```Accessibility problem while visiting inner classes to generate bytecode
allowed enum values to be mutable.

Also fixes a formating problem in `ASTEnumValue.toString````
``` 7c1c720 ```
``` Adds unit tests. ```
``` 4ed0855 ```
``` golodoc integration of enums. ```
``` 3730165 ```
``` Minor changes for conventions ```
```- titles in asciidoc
``` 5b304e1 ```
``` Rename methods in sample code. ```
```rename `bind` to `flatMap` and `fmap` to `map` to mimic the java
`Optional` API.```
``` 4cddf0e ```
``` Rename `enum` to `union`. ```
``` fec5c89 ```
``` Replace footnotes with simple links ```
``` d31d778 ```

### yloiseau added a commit that referenced this pull request May 7, 2015

``` Merge pull request #258 from yloiseau/wip/Enum ```
`Sum algebraic data type`
``` f44a0d8 ```

### yloiseau merged commit `f44a0d8` into eclipse:master May 7, 2015 1 check passed

#### 1 check passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details