| // run -gcflags=-G=3 | |
| // Copyright 2021 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // lice | |
| package main | |
| import "fmt" | |
| // Overriding the predeclare "any", so it can be used as a type constraint or a type | |
| // argument | |
| type any interface{} | |
| type _Function[a, b any] interface { | |
| Apply(x a) b | |
| } | |
| type incr struct{ n int } | |
| func (this incr) Apply(x int) int { | |
| return x + this.n | |
| } | |
| type pos struct{} | |
| func (this pos) Apply(x int) bool { | |
| return x > 0 | |
| } | |
| type compose[a, b, c any] struct { | |
| f _Function[a, b] | |
| g _Function[b, c] | |
| } | |
| func (this compose[a, b, c]) Apply(x a) c { | |
| return this.g.Apply(this.f.Apply(x)) | |
| } | |
| type _Eq[a any] interface { | |
| Equal(a) bool | |
| } | |
| type Int int | |
| func (this Int) Equal(that int) bool { | |
| return int(this) == that | |
| } | |
| type _List[a any] interface { | |
| Match(casenil _Function[_Nil[a], any], casecons _Function[_Cons[a], any]) any | |
| } | |
| type _Nil[a any] struct{ | |
| } | |
| func (xs _Nil[a]) Match(casenil _Function[_Nil[a], any], casecons _Function[_Cons[a], any]) any { | |
| return casenil.Apply(xs) | |
| } | |
| type _Cons[a any] struct { | |
| Head a | |
| Tail _List[a] | |
| } | |
| func (xs _Cons[a]) Match(casenil _Function[_Nil[a], any], casecons _Function[_Cons[a], any]) any { | |
| return casecons.Apply(xs) | |
| } | |
| type mapNil[a, b any] struct{ | |
| } | |
| func (m mapNil[a, b]) Apply(_ _Nil[a]) any { | |
| return _Nil[b]{} | |
| } | |
| type mapCons[a, b any] struct { | |
| f _Function[a, b] | |
| } | |
| func (m mapCons[a, b]) Apply(xs _Cons[a]) any { | |
| return _Cons[b]{m.f.Apply(xs.Head), _Map[a, b](m.f, xs.Tail)} | |
| } | |
| func _Map[a, b any](f _Function[a, b], xs _List[a]) _List[b] { | |
| return xs.Match(mapNil[a, b]{}, mapCons[a, b]{f}).(_List[b]) | |
| } | |
| func main() { | |
| var xs _List[int] = _Cons[int]{3, _Cons[int]{6, _Nil[int]{}}} | |
| var ys _List[int] = _Map[int, int](incr{-5}, xs) | |
| var xz _List[bool] = _Map[int, bool](pos{}, ys) | |
| cs1 := xz.(_Cons[bool]) | |
| cs2 := cs1.Tail.(_Cons[bool]) | |
| _, ok := cs2.Tail.(_Nil[bool]) | |
| if cs1.Head != false || cs2.Head != true || !ok { | |
| panic(fmt.Sprintf("got %v, %v, %v, expected false, true, true", | |
| cs1.Head, cs2.Head, ok)) | |
| } | |
| } |