diff options
Diffstat (limited to 'test/typeparam/cons.go')
-rw-r--r-- | test/typeparam/cons.go | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/test/typeparam/cons.go b/test/typeparam/cons.go new file mode 100644 index 0000000..733e579 --- /dev/null +++ b/test/typeparam/cons.go @@ -0,0 +1,100 @@ +// run + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +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)) + } +} |