import arrow.Proof
import arrow.TypeProof
interface Semigroup {
fun A.combine(other: A): A
interface Syntax {
val value: A
fun combine(other: A): A
}
}
interface Monoid : Semigroup {
fun empty(): A
}
object StringMonoid : Monoid {
override fun String.combine(other: String): String = this + other
override fun empty(): String = ""
}
inline class StringSyntax(override val value: String): Semigroup.Syntax {
override fun combine(other: String): String = value + other
}
@Proof(TypeProof.Extension)
fun String.Companion.monoid(): Monoid = StringMonoid
@Proof(TypeProof.Extension)
fun String.semigroupSyntax(): Semigroup.Syntax = StringSyntax(this)