Skip to content

Instantly share code, notes, and snippets.

@tcard
Last active August 29, 2015 14:27
Show Gist options
  • Save tcard/9a3bb8da3d0c2b0a9993 to your computer and use it in GitHub Desktop.
Save tcard/9a3bb8da3d0c2b0a9993 to your computer and use it in GitHub Desktop.
Tagged unions in Go
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