| // run |
| |
| // Copyright 2022 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" |
| ) |
| |
| // Numeric expresses a type constraint satisfied by any numeric type. |
| type Numeric interface { |
| ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | |
| ~int | ~int8 | ~int16 | ~int32 | ~int64 | |
| ~float32 | ~float64 | |
| ~complex64 | ~complex128 |
| } |
| |
| // Sum returns the sum of the provided arguments. |
| func Sum[T Numeric](args ...T) T { |
| var sum T |
| for i := 0; i < len(args); i++ { |
| sum += args[i] |
| } |
| return sum |
| } |
| |
| // Ledger is an identifiable, financial record. |
| type Ledger[T ~string, K Numeric] struct { |
| // ID identifies the ledger. |
| ID_ T |
| |
| // Amounts is a list of monies associated with this ledger. |
| Amounts_ []K |
| |
| // SumFn is a function that can be used to sum the amounts |
| // in this ledger. |
| SumFn_ func(...K) K |
| } |
| |
| // Field accesses through type parameters are disabled |
| // until we have a more thorough understanding of the |
| // implications on the spec. See issue #51576. |
| // Use accessor methods instead. |
| |
| func (l Ledger[T, _]) ID() T { return l.ID_ } |
| func (l Ledger[_, K]) Amounts() []K { return l.Amounts_ } |
| func (l Ledger[_, K]) SumFn() func(...K) K { return l.SumFn_ } |
| |
| func PrintLedger[ |
| T ~string, |
| K Numeric, |
| L interface { |
| ~struct { |
| ID_ T |
| Amounts_ []K |
| SumFn_ func(...K) K |
| } |
| ID() T |
| Amounts() []K |
| SumFn() func(...K) K |
| }, |
| ](l L) { |
| fmt.Printf("%s has a sum of %v\n", l.ID(), l.SumFn()(l.Amounts()...)) |
| } |
| |
| func main() { |
| PrintLedger(Ledger[string, int]{ |
| ID_: "fake", |
| Amounts_: []int{1, 2, 3}, |
| SumFn_: Sum[int], |
| }) |
| } |