package main

import "fmt"

// section: multiple-params
// Pair represents a pair of values
type Pair[T, U any] struct {
	First  T
	Second U
}

// NewPair creates a new pair
func NewPair[T, U any](first T, second U) Pair[T, U] {
	return Pair[T, U]{First: first, Second: second}
}

// Transform applies a function to convert first to second type
func Transform[T, U any](value T, converter func(T) U) U {
	return converter(value)
}

func main() {
	// When a function has multiple type parameters,
	// the compiler often can't infer all of them

	// This works - compiler can infer both T and U from arguments:
	pair1 := NewPair("hello", 42)
	fmt.Printf("Inferred pair: %+v\n", pair1)

	// But sometimes we need to be explicit:
	pair2 := NewPair[string, int]("world", 100)
	fmt.Printf("Explicit pair: %+v\n", pair2)

	// Transform function needs explicit instantiation
	// because the return type U can't be inferred from the first argument
	result := Transform[int, string](42, func(i int) string {
		return fmt.Sprintf("Number: %d", i)
	})
	fmt.Printf("Transformed: %s\n", result)
}

// section: multiple-params
