代数的データ型とパターンマッチによる言語比較：Koka,Rust,Haxe,Swift,Elm,PureScript,Haskell,OCaml,ReasonML,ReScript,Kotlin,Scala,Dotty,Ruby,Julia,TypeScript

## 代数的データ型

### [Koka](https://github.com/koka-lang/koka)
```koka
type color {
  Red
  Green
  Blue
  Rgb( r : int, g : int, b : int )
}
```

または

```koka
type color {
  Red; Green; Blue; Rgb( r : int, g : int, b : int )
}
```

### Rust
```rust
enum Color {
 Red,
 Green,
 Blue,
 Rgb { r: u8, g: u8, b: u8 }
}
```

### Haxe
```hx
enum Color {
  Red;
  Green;
  Blue;
  Rgb(r: Int, g: Int, b: Int);
}
```

### Swift
```swift
enum Color {
  case Red, Green, Blue, Rgb(r: Int, g: Int, b: Int)
}
```
### Elm
```elm
type Color = Red | Green | Blue | Rgb { r: Int, g: Int, b: Int }
```

### PureScript
```purescript
data Color = Red | Blue | Green | Rgb{ r :: Int, g :: Int, b :: Int }
```

### Haskell
```hs
data Color = Red | Green | Blue | Rgb {r :: Int, g :: Int, b :: Int}
```

### OCaml
```ocaml
type rgb = { r: int; g: int; b: int }
type color = Red | Green | Blue | Rgb of rgb
```

### ReasonML
```reasonml
type rgb = { r: int, g: int, b: int };
type color =
  | Red
  | Green
  | Blue
  | Rgb(rgb);
```
### ReScript
```rescript
type color = Red | Green | Blue | Rgb({r: int, g: int, b: int})
```

### Kotlin
```kotlin
sealed class Color {
    object Red: Color()
    object Green: Color()
    object Blue: Color()
    class Rgb(val r: Int,val  g: Int,val  b: Int): Color()
}
```

### Scala
```scala
sealed trait Color

final case object Red extends Color
final case object Green extends Color
final case object Blue extends Color
final case class Rgb(r: Int, g: Int, b: Int) extends Color
```

### Dotty(Scala 3)
```scala
enum Color {
  case Red
  case Green
  case Blue
  case Rgb(r: Int, g: Int, b: Int)
}
```

### Julia
```julia
@enum ColorBase red blue green
struct Rgb
 r::UInt8
 g::UInt8
 b::UInt8
end
Color = Union{ColorBase,Rgb}
```

### TypeScript
```ts
type Color = Red | Green | Blue | Rgb;
const enum ColorKind {
  Red = "Red",
  Green = "Green",
  Blue = "Blue",
  Rgb = "Rgb"
}

interface Red {
    kind: ColorKind.Red;
}

interface Green {
    kind: ColorKind.Green;
}

interface Blue {
    kind: ColorKind.Blue;
}

interface Rgb {
    kind: ColorKind.Rgb;
    r: number;
    g: number;
    b: number;
}
```

### Ruby
```rb
module Color
  Red = 1
  Green = 2
  Blue = 3
  Rgb = Struct.new(:r, :g, :b)
end
```

### 感想
#### 記法
1. Koka, Rust, Haxe, Elm: とても良い
2. Dotty, Swift, PureScript, Haskell, OCaml, ReasonML, ReScript: 良い
3. Ruby: 普通
4. Kotlin: 書きにくい
5. Scala: とても書きにくい

## パターンマッチ

### Koka
```koka
match(color) {
  Red   -> "#FF0000"
  Green -> "#00FF00"
  Blue  -> "#0000FF"
  Rgb(r,g,b) -> "#" + showHex(r,2) + showHex(g,2) + showHex(b,2)
}
```
[view code](https://gist.github.com/xmeta/2f1e9ca0e945aaa59f3326eadbdece84#file-color-kk)
### Rust
```rust
match color {
    Color::Red   => "#FF0000".to_string(),
    Color::Green => "#00FF00".to_string(),
    Color::Blue  => "#0000FF".to_string(),
    Color::Rgb{r, g, b} => format!("#{:02X}{:02X}{:02X}", r, g, b),
}
```
[view code](http://ideone.com/UPBv5v)

### Haxe
```hx
switch( color ) {
  case Red:   "#FF0000";
  case Green: "#00FF00";
  case Blue:  "#0000FF";
  case Rgb(r, g, b): "#"+ StringTools.hex(r,2) + StringTools.hex(g,2) + StringTools.hex(b,2);
}
```
- [view code](http://try.haxe.org/#6e52E)
- [view code](http://try.haxe.org/#d5e66)

### Swift
```swift
switch color {
  case .Red:
    return "#FF0000"
  case .Green:
    return "#00FF00"
  case .Blue:
    return "#0000FF"
  case let .Rgb(r, g, b):
    return String(format:"#%02X%02X%02X", r, g, b)
}
```
[view code](https://gist.github.com/xmeta/ad3768e2330637d1f0f07985417aaf4f)

### Elm
```elm
case color of
    Red   -> "#FF0000"
    Green -> "#00FF00"
    Blue  -> "#0000FF"
    Rgb {r, g, b} -> String.concat ["#", (toHex r), (toHex g), (toHex b)]
```
* [view code](https://glot.io/snippets/fvapyrwy55)
* [view code](https://gist.github.com/xmeta/2f1e9ca0e945aaa59f3326eadbdece84)

### PureScript
```purescript
case color of
  Red   -> "#FF0000"
  Green -> "#00FF00"
  Blue  -> "#0000FF"
  Rgb { r, g, b } -> "#" <> toHex r <>  toHex g <>  toHex b 
```
[view code](http://try.purescript.org/?gist=006f6dedcafb18d2fd8aca138c720ef5)

### Haskell
```hs
case color of
    Red   -> "#FF0000"
    Green -> "#00FF00"
    Blue  -> "#0000FF"
    Rgb r g b -> printf "#%02X%02X%02X" r g b
```
[view code](http://ideone.com/wYlJaI)

### OCaml
```ocaml
match color with
      Red   -> "#FF0000"
    | Green -> "#00FF00"
    | Blue  -> "#0000FF"
    | Rgb {r; g; b} -> Printf.sprintf "#%02X%02X%02X" r g b;;
```
[view code](http://ideone.com/YjJZ7M)

### ReasonML
```reasonml
switch (color) {
| Red => "#FF000"
| Green => "#00FF00"
| Blue => "#0000FF"
| Rgb({r, g, b}) => "#" ++ numToHex(r) ++ numToHex(g) ++ numToHex(b)
```
[view code](https://reasonml.github.io/en/try.html?rrjsx=false&reason=DYUwLgBAdgrgtgFQPYAkQA8IF4IEtsB8EA3gFAQSiSQ4BEADPbRANQsQBSAzgHQCSUMDzBIAymABOuKAHMA6rjAALAEoBDACa50AClwAaCAD8Jm7VgCMANgCUAbnKde4qbIBMPLsFwBjEDrBDIwAzCSQ4LABaNyCRAH0sbh4XaRkeUFllAJt7UgBfB1IwAE8ABxAICRkAI2wSRwkALjxBfUcZZulAx2rO1vzCkvKIHyRgJAlsRwAfCBUQDRmIAHEJEBAoJYAhYBgQJZUanSrq3NIqCBE0TBxR8cmsAkcuAHdFHyUIHTuJm3qKWbzDSECC0ADEADEIYwmEtVusoCDwYwoYxaNtdhVHqCwTD6FD0QC5kdiBJDDJDNU8n9Ho4KODCRRWOwdLBEKgMMc-mxoPBkNcdDJuew2fzOacbJECEkUrJhEgAKqlcoSADCai4+woBVI53AEBeSkUWOJ1R0pOabgArFbyZabZT7VbqYUkuMZAEObpDcacg4gA)

### ReScript
```rescript
switch color {
| Red => "#FF000"
| Green => "#00FF00"
| Blue => "#0000FF"
| Rgb({r, g, b}) => "#" ++ numToHex(r) ++ numToHex(g) ++ numToHex(b)
}
```
[view code](https://rescript-lang.org/try?code=AIZwpgdgJgBGAeAXMAnCBDANjADuqAyouiogOoCWiAFgFwwAUIiKFEA5gDQxuLfOsOAShgBeAHwwBbdmJgAiPIWKl5AKDWIAnjjAwAxgHtMhlHIBKYWAB8YAcRRhIMWwCFMAVz23z7AEYMAN4o9Lzc7KEQfDB+kYgAvkJqmGCIMBAeALYAKoYAEghyFGKSgWowuPhEJORU1AwAUiAAdACSUc2IhkSC7JQ05vgU8AwU3AB+KEPwogCMAGxC3ABM3PIADPJJ8RoA9LswBB44OKZprQCiyanpWbkF8ABippdFJTBlFSlpaaIK65sYABqIEwJptDpdHoyfrUQZQYajCZTBEzBZJCrg6EcZbNECYCj6MAMaLjABmKEMmVEAFpVjBxl0APqiLEsGTNFIcGgkoTbDTfGBdB5yIwmMwScpSADuVH01AMxlMHylPis73kAGJHo8AZtVfZHM4JApNQCdQD1BU3J49CatXr1jqrS4YL4AsFwtw-IkSlKKlr5MDQZ8KmHDLoIGCWgBBFBTLTLf1hgDaKC9MQAujTxJl0DgGBkcvkEEIcwArQxsWEMeRbHNs3qdQwAVROqAAwuhwMmdhUdtc0tLqFQ7W7-EEQjBlgBWGfheiz+cxRdzxKaEsjYejsvicEmdhqIA)

### Kotlin
```kotlin
when ( color ) {
  Color.Red   -> "#FF0000"
  Color.Green -> "#00FF00"
  Color.Blue  -> "#0000FF"
  is Color.Rgb -> "#%02X%02X%02X".format(color.r, color.g, color.b)
}
```
[view code](https://gist.github.com/xmeta/70e07b542a7e5d2b9c4c98428b07596e)

### Scala
```scala
color match {
  case Red   =>"#FF0000"
  case Green =>"#00FF00"
  case Blue  =>"#0000FF"
  case Rgb(r, g, b) => "#%02X%02X%02X".format(r, g, b)
}
```
[view code](http://ideone.com/YbswFA)

### Dotty(Scala 3)
```scala
color match {
  case Color.Red   => "#FF0000"
  case Color.Green => "#00FF00"
  case Color.Blue  => "#0000FF"
  case Color.Rgb(r, g, b) => "#%02X%02X%02X".format(r, g, b)
}
```
[view code](https://scastie.scala-lang.org/2uoFXzhvRv2ZK8Cl0jCdlA)

### Julia
```julia
if color == red
  return "#FF0000"
elseif color == blue
  return "#00FF00"
elseif color == green
  return "#0000FF"
elseif typeof(color) == Rgb
  hex = (x) -> uppercase(string(x, base=16, pad=2))
  return string("#", hex(color.r), hex(color.g), hex(color.b))
end
```
[view code](https://gist.github.com/xmeta/2f1e9ca0e945aaa59f3326eadbdece84#file-color-jl)

### TypeScript
```ts
switch (color.kind) {
    case ColorKind.Red: return "#FF0000";
    case ColorKind.Green: return "#00FF00";
    case ColorKind.Blue: return "#0000FF";
    case ColorKind.Rgb: return "#" + [color.r, color.g, color.b].map((v) => v.toString(16)).join('').toUpperCase();
    default:
        const _exhaustiveCheck: never = color;
        return _exhaustiveCheck;
}
```
[view code](https://www.typescriptlang.org/play?ts=4.6.2#code/C4TwDgpgBAwg9gGzgJygXigJQgEygHygHFkIIA7AqAIQQFdpDMBzAIwG4BYAKAGM5yAZ2BQKdALaxEKANIBLcngDePKFlzooAImw4tAGlXFSFTVpJlyBo7QZnbEa9zUtWZ11p4BfHjwXAIZAAzAENeaF0oFWc1KABrBRwALikkZHlFADpdLm4fbj9yAOCw6AtTaNj4xJT4NIycTPLyXPzC4tDwmnpoStiExVrpdMTMh1bfbn9Azoi2KKM1AeTU2VHXXKrkFPIJVkDN2OYdvYPFqFYT8X3kCYLuILpyXmA5AShgOAAJCAAPAAp+GkhmkAJQpYTIBTMBYxNSCADucmAvAAFlBAcNMstQbCqlVeCFBNA6mssroUqRgHRkJQtABiABijIADGyWVpDvioITiasRllmpSINTadp6WzmWzOecCUSScMGmMesLRXSJezmTK4fjeQr6us2KqaeqtFAANRQADaQJQmWQ+h5WOYjttyEyrAAuplxCEwP9-gA3XFoAB8UEDmU+AGVgFDyMx-gBGABsoMyYBCOFjIWQwH+ACZHQByFnF0HpgBWcAU-2L5ajcAAqmBIMgYPL-qCuficBBQnQEMAkrLuU6hCIAPp-VEhOjCOSBiAwVEQXhxHYQJeoDBuntjqBUk1Qae-Wfz15LldruI9-JtbgIEU8lKuTR9JY1flK1yGHXbKAkzZP8qmOKAC2A85LkAyC8kmEInzzf5Ph+AFeArXIgA)

### Ruby
```rb
case color
when Color::Red; "#FF000"
when Color::Green; "#00FF00"
when Color::Blue; "#0000FF"
when Color::Rgb; "#%02X%02X%02X" % [color.r, color.g, color.b]
end
```
[view code](http://ideone.com/YFHGYT)

### 感想
#### 記法
1. Koka, Rust, Elm, PureScript, Haskell: とても良い
2. OCaml, ReasonML, ReScript, Kotlin: 良い
3. Haxe, Scala, Dotty, Ruby: 普通
4. TypeScript, Swift: 書きにくい

#### コンパイラデフォルト動作
1. Rust, Haxe, Swift, Kotlin, Elm, PureScript: パターンを網羅していないとコンパイルエラーになる
2. Scala, Dotty, OCaml, ReasonML, ReScript: パターンを網羅していなくても警告するだけでコンパイルが通ってしまう
3. Koka, Haskell: パターンを網羅していなくても警告なしでコンパイルが通ってしまう
4. Ruby: 論外