// FIR_IDENTICAL // !LANGUAGE: +ContextReceivers interface Semigroup { infix fun T.combine(other: T): T } interface Monoid : Semigroup { val unit: T } object IntMonoid : Monoid { override fun Int.combine(other: Int): Int = this + other override val unit: Int = 0 } object StringMonoid : Monoid { override fun String.combine(other: String): String = this + other override val unit: String = "" } public inline fun Iterable.fold(initial: R, operation: (acc: R, T) -> R): R = TODO() context(Monoid) fun List.sum(): T = fold(unit) { acc, e -> acc.combine(e) } fun listOf(vararg items: T): List = null!! fun test() { with(IntMonoid) { listOf(1, 2, 3).sum() } with(StringMonoid) { listOf(1, 2, 3).sum() listOf("1", "2", "3").sum() } }