Source file test/typeparam/cons.go

     1  // run
     2  
     3  // Copyright 2021 The Go Authors. All rights reserved.
     4  // Use of this source code is governed by a BSD-style
     5  // license that can be found in the LICENSE file.
     6  
     7  package main
     8  
     9  import "fmt"
    10  
    11  // Overriding the predeclare "any", so it can be used as a type constraint or a type
    12  // argument
    13  type any interface{}
    14  
    15  type Function[a, b any] interface {
    16  	Apply(x a) b
    17  }
    18  
    19  type incr struct{ n int }
    20  
    21  func (this incr) Apply(x int) int {
    22  	return x + this.n
    23  }
    24  
    25  type pos struct{}
    26  
    27  func (this pos) Apply(x int) bool {
    28  	return x > 0
    29  }
    30  
    31  type compose[a, b, c any] struct {
    32  	f Function[a, b]
    33  	g Function[b, c]
    34  }
    35  
    36  func (this compose[a, b, c]) Apply(x a) c {
    37  	return this.g.Apply(this.f.Apply(x))
    38  }
    39  
    40  type _Eq[a any] interface {
    41  	Equal(a) bool
    42  }
    43  
    44  type Int int
    45  
    46  func (this Int) Equal(that int) bool {
    47  	return int(this) == that
    48  }
    49  
    50  type List[a any] interface {
    51  	Match(casenil Function[Nil[a], any], casecons Function[Cons[a], any]) any
    52  }
    53  
    54  type Nil[a any] struct {
    55  }
    56  
    57  func (xs Nil[a]) Match(casenil Function[Nil[a], any], casecons Function[Cons[a], any]) any {
    58  	return casenil.Apply(xs)
    59  }
    60  
    61  type Cons[a any] struct {
    62  	Head a
    63  	Tail List[a]
    64  }
    65  
    66  func (xs Cons[a]) Match(casenil Function[Nil[a], any], casecons Function[Cons[a], any]) any {
    67  	return casecons.Apply(xs)
    68  }
    69  
    70  type mapNil[a, b any] struct {
    71  }
    72  
    73  func (m mapNil[a, b]) Apply(_ Nil[a]) any {
    74  	return Nil[b]{}
    75  }
    76  
    77  type mapCons[a, b any] struct {
    78  	f Function[a, b]
    79  }
    80  
    81  func (m mapCons[a, b]) Apply(xs Cons[a]) any {
    82  	return Cons[b]{m.f.Apply(xs.Head), Map[a, b](m.f, xs.Tail)}
    83  }
    84  
    85  func Map[a, b any](f Function[a, b], xs List[a]) List[b] {
    86  	return xs.Match(mapNil[a, b]{}, mapCons[a, b]{f}).(List[b])
    87  }
    88  
    89  func main() {
    90  	var xs List[int] = Cons[int]{3, Cons[int]{6, Nil[int]{}}}
    91  	var ys List[int] = Map[int, int](incr{-5}, xs)
    92  	var xz List[bool] = Map[int, bool](pos{}, ys)
    93  	cs1 := xz.(Cons[bool])
    94  	cs2 := cs1.Tail.(Cons[bool])
    95  	_, ok := cs2.Tail.(Nil[bool])
    96  	if cs1.Head != false || cs2.Head != true || !ok {
    97  		panic(fmt.Sprintf("got %v, %v, %v, expected false, true, true",
    98  			cs1.Head, cs2.Head, ok))
    99  	}
   100  }
   101  

View as plain text