Skip to content

Instantly share code, notes, and snippets.

@nomisRev
Created November 26, 2017 14:54
Show Gist options
  • Save nomisRev/0f98f8dee8675244e77db837636d8bf6 to your computer and use it in GitHub Desktop.
Save nomisRev/0f98f8dee8675244e77db837636d8bf6 to your computer and use it in GitHub Desktop.
KeyValueStore with Free in Kategory
@higherkind sealed class KeyValueStore<A> : KeyValueStoreKind<A> {
companion object : FreeMonadInstance<KeyValueStoreHK>
}
data class Put<A>(val key: String, val value: A) : KeyValueStore<A>()
data class Get<A>(val key: String) : KeyValueStore<Option<A>>()
data class Delete(val key: String) : KeyValueStore<Unit>()
object Clear : KeyValueStore<Unit>()
typealias FreeKeyValueStore<A> = Free<KeyValueStoreHK, A>
fun <A> put(key: String, value: A): FreeKeyValueStore<A> =
Free.liftF(Put(key, value))
fun <A> get(key: String): FreeKeyValueStore<Option<A>> =
Free.liftF(Get(key))
fun delete(key: String): FreeKeyValueStore<Unit> =
Free.liftF(Delete(key))
fun clear(): FreeKeyValueStore<Unit> =
Free.liftF(Clear)
fun <A> update(key: String, f: (A) -> A) = KeyValueStore.binding {
val opt = get<A>(key).bind()
opt.fold(
ifEmpty = { KeyValueStore.pure(Unit) },
f= { v -> put(key, f(v)) }
).bind()
yields(Unit)
}.ev()
fun program(): FreeKeyValueStore<Option<Int>> = KeyValueStore.binding {
put("wild-cats", 2).bind()
update<Int>("wild-cats") { it + 12 }.bind()
put("tame-cats", 5).bind()
val n = get<Int>("wild-cats").bind()
delete("tame-cats").bind()
yields(n)
}.ev()
typealias KeyValueStoreStateHK = StateTKindPartial<IdHK, Map<String, Any>>
val pureCompiler = object : FunctionK<KeyValueStoreHK, KeyValueStoreStateHK> {
override fun <A> invoke(fa: HK<KeyValueStoreHK, A>): HK<KeyValueStoreStateHK, A> {
val op = fa.ev()
return when (op) {
is Put -> State { state: Map<String, Any> ->
state.k().updated(op.key, op.value as Any) toT op.value
}
is Get<*> -> State { state: Map<String, Any> ->
state toT state.getOption(op.key).map { it as A }
}
is Delete -> State { state: Map<String, Any> ->
state - op.key toT Unit
}
Clear -> State { _ : Map<String, Any> ->
emptyMap<String, Any>() toT Unit
}
} as HK<KeyValueStoreStateHK, A>
}
}
fun main(args: Array<String>) {
program().foldMap(pureCompiler, State.monad())
.runM(emptyMap())
.let(::println)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment