Source file test/typeparam/issue50485.dir/a.go

     1  package a
     2  
     3  import "fmt"
     4  
     5  type ImplicitOrd interface {
     6  	~int | ~int8 | ~int16 | ~int32 | ~int64 |
     7  		~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
     8  		~float32 | ~float64 |
     9  		~string
    10  }
    11  
    12  func LessGiven[T ImplicitOrd]() Ord[T] {
    13  	return LessFunc[T](func(a, b T) bool {
    14  		return a < b
    15  	})
    16  }
    17  
    18  type Eq[T any] interface {
    19  	Eqv(a T, b T) bool
    20  }
    21  
    22  type Ord[T any] interface {
    23  	Eq[T]
    24  	Less(a T, b T) bool
    25  }
    26  
    27  type LessFunc[T any] func(a, b T) bool
    28  
    29  func (r LessFunc[T]) Eqv(a, b T) bool {
    30  	return r(a, b) == false && r(b, a) == false
    31  }
    32  
    33  func (r LessFunc[T]) Less(a, b T) bool {
    34  	return r(a, b)
    35  }
    36  
    37  type Option[T any] struct {
    38  	v *T
    39  }
    40  
    41  func (r Option[T]) IsDefined() bool {
    42  	return r.v != nil
    43  }
    44  
    45  func (r Option[T]) IsEmpty() bool {
    46  	return !r.IsDefined()
    47  }
    48  
    49  func (r Option[T]) Get() T {
    50  	return *r.v
    51  }
    52  
    53  func (r Option[T]) String() string {
    54  	if r.IsDefined() {
    55  		return fmt.Sprintf("Some(%v)", r.v)
    56  	} else {
    57  		return "None"
    58  	}
    59  }
    60  
    61  func (r Option[T]) OrElse(t T) T {
    62  	if r.IsDefined() {
    63  		return *r.v
    64  	}
    65  	return t
    66  }
    67  
    68  func (r Option[T]) Recover(f func() T) Option[T] {
    69  	if r.IsDefined() {
    70  		return r
    71  	}
    72  	t := f()
    73  	return Option[T]{&t}
    74  }
    75  
    76  type Func1[A1, R any] func(a1 A1) R
    77  
    78  type Func2[A1, A2, R any] func(a1 A1, a2 A2) R
    79  
    80  func (r Func2[A1, A2, R]) Curried() Func1[A1, Func1[A2, R]] {
    81  	return func(a1 A1) Func1[A2, R] {
    82  		return Func1[A2, R](func(a2 A2) R {
    83  			return r(a1, a2)
    84  		})
    85  	}
    86  }
    87  
    88  type HList interface {
    89  	sealed()
    90  }
    91  
    92  // Header is constrains interface type,  enforce Head type of Cons is HT
    93  type Header[HT any] interface {
    94  	HList
    95  	Head() HT
    96  }
    97  
    98  // Cons means H :: T
    99  // zero value of Cons[H,T] is not allowed.
   100  // so Cons defined as interface type
   101  type Cons[H any, T HList] interface {
   102  	HList
   103  	Head() H
   104  	Tail() T
   105  }
   106  
   107  type Nil struct {
   108  }
   109  
   110  func (r Nil) Head() Nil {
   111  	return r
   112  }
   113  
   114  func (r Nil) Tail() Nil {
   115  	return r
   116  }
   117  
   118  func (r Nil) String() string {
   119  	return "Nil"
   120  }
   121  
   122  func (r Nil) sealed() {
   123  
   124  }
   125  
   126  type hlistImpl[H any, T HList] struct {
   127  	head H
   128  	tail T
   129  }
   130  
   131  func (r hlistImpl[H, T]) Head() H {
   132  	return r.head
   133  }
   134  
   135  func (r hlistImpl[H, T]) Tail() T {
   136  	return r.tail
   137  }
   138  
   139  func (r hlistImpl[H, T]) String() string {
   140  	return fmt.Sprintf("%v :: %v", r.head, r.tail)
   141  }
   142  
   143  func (r hlistImpl[H, T]) sealed() {
   144  
   145  }
   146  
   147  func hlist[H any, T HList](h H, t T) Cons[H, T] {
   148  	return hlistImpl[H, T]{h, t}
   149  }
   150  
   151  func Concat[H any, T HList](h H, t T) Cons[H, T] {
   152  	return hlist(h, t)
   153  }
   154  
   155  func Empty() Nil {
   156  	return Nil{}
   157  }
   158  func Some[T any](v T) Option[T] {
   159  	return Option[T]{}.Recover(func() T {
   160  		return v
   161  	})
   162  }
   163  
   164  func None[T any]() Option[T] {
   165  	return Option[T]{}
   166  }
   167  
   168  func Ap[T, U any](t Option[Func1[T, U]], a Option[T]) Option[U] {
   169  	return FlatMap(t, func(f Func1[T, U]) Option[U] {
   170  		return Map(a, f)
   171  	})
   172  }
   173  
   174  func Map[T, U any](opt Option[T], f func(v T) U) Option[U] {
   175  	return FlatMap(opt, func(v T) Option[U] {
   176  		return Some(f(v))
   177  	})
   178  }
   179  
   180  func FlatMap[T, U any](opt Option[T], fn func(v T) Option[U]) Option[U] {
   181  	if opt.IsDefined() {
   182  		return fn(opt.Get())
   183  	}
   184  	return None[U]()
   185  }
   186  
   187  type ApplicativeFunctor1[H Header[HT], HT, A, R any] struct {
   188  	h  Option[H]
   189  	fn Option[Func1[A, R]]
   190  }
   191  
   192  func (r ApplicativeFunctor1[H, HT, A, R]) ApOption(a Option[A]) Option[R] {
   193  	return Ap(r.fn, a)
   194  }
   195  
   196  func (r ApplicativeFunctor1[H, HT, A, R]) Ap(a A) Option[R] {
   197  	return r.ApOption(Some(a))
   198  }
   199  
   200  func Applicative1[A, R any](fn Func1[A, R]) ApplicativeFunctor1[Nil, Nil, A, R] {
   201  	return ApplicativeFunctor1[Nil, Nil, A, R]{Some(Empty()), Some(fn)}
   202  }
   203  
   204  type ApplicativeFunctor2[H Header[HT], HT, A1, A2, R any] struct {
   205  	h  Option[H]
   206  	fn Option[Func1[A1, Func1[A2, R]]]
   207  }
   208  
   209  func (r ApplicativeFunctor2[H, HT, A1, A2, R]) ApOption(a Option[A1]) ApplicativeFunctor1[Cons[A1, H], A1, A2, R] {
   210  
   211  	nh := FlatMap(r.h, func(hv H) Option[Cons[A1, H]] {
   212  		return Map(a, func(av A1) Cons[A1, H] {
   213  			return Concat(av, hv)
   214  		})
   215  	})
   216  
   217  	return ApplicativeFunctor1[Cons[A1, H], A1, A2, R]{nh, Ap(r.fn, a)}
   218  }
   219  func (r ApplicativeFunctor2[H, HT, A1, A2, R]) Ap(a A1) ApplicativeFunctor1[Cons[A1, H], A1, A2, R] {
   220  
   221  	return r.ApOption(Some(a))
   222  }
   223  
   224  func Applicative2[A1, A2, R any](fn Func2[A1, A2, R]) ApplicativeFunctor2[Nil, Nil, A1, A2, R] {
   225  	return ApplicativeFunctor2[Nil, Nil, A1, A2, R]{Some(Empty()), Some(fn.Curried())}
   226  }
   227  func OrdOption[T any](m Ord[T]) Ord[Option[T]] {
   228  	return LessFunc[Option[T]](func(t1 Option[T], t2 Option[T]) bool {
   229  		if !t1.IsDefined() && !t2.IsDefined() {
   230  			return false
   231  		}
   232  		return Applicative2(m.Less).ApOption(t1).ApOption(t2).OrElse(!t1.IsDefined())
   233  	})
   234  }
   235  
   236  func Given[T ImplicitOrd]() Ord[T] {
   237  	return LessGiven[T]()
   238  }
   239  

View as plain text