Skip to content

Instantly share code, notes, and snippets.

@RayStarkMC
Last active September 4, 2023 14:58
Show Gist options
  • Save RayStarkMC/0afa471beb30d5c5225ae3a7709de9cd to your computer and use it in GitHub Desktop.
Save RayStarkMC/0afa471beb30d5c5225ae3a7709de9cd to your computer and use it in GitHub Desktop.
Kotlinで作れなかったST

Kotlinで作るST

//TODO 解説

@DslMarker
annotation class STDsl
fun main() {
val ref = runST {
object : ST<STRef<*, String>> {
override fun <S> STScope<S>.invoke() = run {
val ref = newSTRef("hello world")
val result = ref.readSTRef()
println(result)
ref
}
}
}
// ref.readSTRef() CE!!!!!!
}
sealed interface STRef<S, A>
private class STRefImpl<S, A>(var a: A) : STRef<S, A>
@STDsl
interface ST<A> {
@STDsl
operator fun <S> STScope<S>.invoke(): A
}
@STDsl
data class STScope<S>(val s: S) {
@STDsl
fun <A> newSTRef(a: A): STRef<S, A> = STRefImpl(a)
@STDsl
fun <A> STRef<S, A>.modifySTRef(f: (A) -> A) {
when (this) {
is STRefImpl -> a = f(a)
}
}
@STDsl
fun <A> STRef<S, A>.readSTRef(): A = when (this) {
is STRefImpl -> a
}
@STDsl
fun <A> ST<A>.bind(): A = run {
STScope(Unit)()
}
}
@STDsl
fun <A> runST(block: () -> ST<A>): A = block().run {
STScope(Unit)()
}
@STDsl
fun <A, B> ST<A>.map(f: (A) -> B): ST<B> = object : ST<B> {
override fun <S> STScope<S>.invoke(): B =
runST { this@map }.let(f)
}
@STDsl
fun <A, B> ST<A>.flatMap(f: (A) -> ST<B>): ST<B> = object : ST<B> {
override fun <S> STScope<S>.invoke(): B =
runST { this@flatMap }.let(f).bind()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment