// 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)) } }