Last active
August 29, 2015 14:27
-
-
Save tcard/9a3bb8da3d0c2b0a9993 to your computer and use it in GitHub Desktop.
Tagged unions in Go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"unsafe" | |
) | |
// data Shape a = Circle { radius :: a } | Rect { base :: a, height :: a} | Together { left :: Shape a, right :: Shape a } | |
type ID_shape_float64 struct { | |
TAG int // Can be 0 (circle), 1 (rect), or 2 (together) | |
PAYLOAD [16]byte // sizeof(*ANON_shape_float64_together), the biggest one | |
} | |
type ANON_shape_float64_circle struct { | |
ID_radius float64 | |
} | |
type ANON_shape_float64_rect struct { | |
ID_base float64 | |
ID_height float64 | |
} | |
type ANON_shape_float64_together struct { | |
ID_left *ID_shape_float64 | |
ID_right *ID_shape_float64 | |
} | |
// area :: Num a => Shape a -> a | |
func (shape ID_shape_float64) area() float64 { | |
// case shape of | |
switch shape.TAG { | |
// v@(Circle _) -> radius v * 3.14159 * 3.14159 | |
case 0: | |
p := *(*ANON_shape_float64_circle)(unsafe.Pointer(&shape.PAYLOAD)) | |
return p.ID_radius * 3.14159 * 3.14159 | |
// v@(Rect _ _) -> base v * height v | |
case 1: | |
p := *(*ANON_shape_float64_rect)(unsafe.Pointer(&shape.PAYLOAD)) | |
return p.ID_base * p.ID_height | |
// v@(Together _ _) -> shape v + shape v | |
case 2: | |
p := *(*ANON_shape_float64_together)(unsafe.Pointer(&shape.PAYLOAD)) | |
return p.ID_left.area() + p.ID_right.area() | |
} | |
panic("non-exhaustive pattern blablablah") | |
} | |
func main() { | |
// let shape = Circle{radius = 4} | |
shape := ID_shape_float64{ | |
TAG: 0, | |
} | |
p := ANON_shape_float64_circle{4} | |
copy(shape.PAYLOAD[:], (*(*[unsafe.Sizeof(p)]byte)(unsafe.Pointer(&p)))[:]) | |
fmt.Println("Circle{radius = 4} area:", shape.area()) | |
// let shape2 = Rect{base = 2, height = 3} | |
shape2 := ID_shape_float64{ | |
TAG: 1, | |
} | |
p2 := ANON_shape_float64_rect{2, 3} | |
copy(shape2.PAYLOAD[:], (*(*[unsafe.Sizeof(p2)]byte)(unsafe.Pointer(&p2)))[:]) | |
fmt.Println("Rect{base = 2, height = 3} area:", shape2.area()) | |
// let shape3 = Together{left = shape, right = shape2} | |
shape3 := ID_shape_float64{ | |
TAG: 2, | |
} | |
p3 := ANON_shape_float64_together{&shape, &shape2} | |
copy(shape3.PAYLOAD[:], (*(*[unsafe.Sizeof(p3)]byte)(unsafe.Pointer(&p3)))[:]) | |
fmt.Println("Together{left = shape, right = shape2} area:", shape3.area()) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment