Kristian Nedrevold
11/09/2022, 9:47 PMsimon.vergauwen
11/10/2022, 7:12 AMcontext(Monoid<A>)
fun List<A>.combineAll(): A =
fold(empty()) { acc, a ->
acc.combine(a)
}
simon.vergauwen
11/10/2022, 7:15 AMlistOf(1, 2, 3).combineAll()
won't compile, and you will have to do.
with(IntMonoid) {
listOf(1, 2, 3).combineAll()
}
There are some ongoing experiments to solve this piece in a compiler plugin within the Arrow organisation, but compiler plugins won't be stable until Kotlin 1.9.simon.vergauwen
11/10/2022, 7:18 AMwith
for multiple arguments.
interface Service
interface Persistence
object Error
object User
context(
Service,
Persistence,
Raise<Error>
)
suspend fun fetch(): User {
// service, persistence available
// suspend (IO) available
// Can raise typed errors of Error
return User
}
fun main() = runBlocking {
with(service(), persistence()) {
either {
fetch()
}.let(println) // Right(User)
}
}
Kristian Nedrevold
11/10/2022, 9:34 AMEmil Kantis
11/10/2022, 10:04 PMcompiler plugins won't be stable until Kotlin 1.9.Looks like later than that, even. https://kotlinlang.slack.com/archives/C7L3JB43G/p1668103693929499
Kristian Nedrevold
11/14/2022, 5:46 PMinterface Shape<T> {
fun perimeter(shape: T): Double
fun area(shape: T): Double
}
context(Shape<T>)
fun <T>prettyPrint(shape : T) = "Perimeter: ${perimeter(shape)} Area: ${area(shape)})})}"
object SquareShape : Shape<Square> {
override fun perimeter(shape: Square): Double = shape.side * 4.0
override fun area(shape: Square): Double = shape.side * shape.side.toDouble()
}
object CircleShape : Shape<Circle> {
override fun perimeter(shape: Circle): Double = 2 * Math.PI * shape.radius
override fun area(shape: Circle): Double = Math.PI * shape.radius * shape.radius
}
data class Square(val side: Int)
data class Rectangle(val width: Int, val height: Int)
data class Cube(val side: Int)
data class Cuboid(val width: Int, val height: Int, val depth: Int)
data class Circle(val radius: Int)
fun main() {
val square = Square(10)
val circle = Circle(10)
val rectangle = Rectangle(10, 20)
with(SquareShape) {
println(prettyPrint(square))
}
with(CircleShape) {
println(prettyPrint(circle))
}
println(prettyPrint(rectangle)) // Will not compile until we add a RectangleShape context
}
So this would be a way to use context right?Kristian Nedrevold
11/14/2022, 5:47 PMinterface Shape<T> {
fun perimeter(shape: T): Double
fun area(shape: T): Double
}
context(Shape<T>)
fun <T>prettyPrint(shape : T) = "Perimeter: ${perimeter(shape)} Area: ${area(shape)})})}"
is the type class equivalent in this case?Kristian Nedrevold
11/14/2022, 5:49 PMKristian Nedrevold
11/14/2022, 5:51 PMKristian Nedrevold
11/16/2022, 8:14 PM@OptIn(ExperimentalContracts::class)
inline fun <A, B, R> with(receiver1: A, receiver2: B, block: A.(B) -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return receiver1.block(receiver2)
}
but that captures receiver2 so it doesn't work.simon.vergauwen
11/17/2022, 7:08 AMinline fun <A, B, R> with(a: A, b: B, block: context(A, B) (TypePlacedHolder<B>) -> R): R {
contract { callsInPlace(block, EXACTLY_ONCE) }
return block(a, b, TypePlacedHolder)
}
sealed interface TypePlacedHolder<out A> {
companion object : TypePlacedHolder<Nothing>
}
Kristian Nedrevold
11/17/2022, 8:31 AM