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