Last active
August 7, 2017 12:31
-
-
Save go-cristian/bdb3286aa35f06634e9b32c725a4eec4 to your computer and use it in GitHub Desktop.
Code based on Matthias Käppler's post about Monoids and Sum Types, check https://medium.com/@mttkay/refactoring-with-monoids-and-sum-types-part-1-bddc9ea61f5f for the complete explanation of this code. Thanks to @mttkay for the excellent blogpost!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.Arrays | |
val inventory = Array<Elem>(size = 3) { Empty } | |
fun main(args: Array<String>) { | |
val sword1 = Sword("Sword 1") | |
val sword2 = Sword("Sword 2") | |
val pickaxe = Pickaxe("Pickaxe 1") | |
val item1 = Item(sword1) | |
val item2 = Item(sword2) | |
val item3 = Item(pickaxe) | |
val stack = item1 + item2 // creates an ItemStack | |
val stillItem1 = Empty + item1 // this compiles and works! | |
inventory[0] = item1 | |
inventory[1] = item2 | |
inventory[2] = item3 | |
move(inventory, 0, 1) | |
move(inventory, 2, 1) | |
println(Arrays.deepToString(inventory)) | |
} | |
fun move(inventory: Array<Elem>, from: Int, to: Int) { | |
inventory[to] = inventory[to] + inventory[from] | |
inventory[from] = Empty | |
} | |
sealed class GameObject | |
data class Pickaxe(val name: String) : GameObject() | |
data class Sword(val name: String) : GameObject() | |
sealed class Elem { | |
abstract operator fun plus(el: Elem): Elem | |
inline fun yieldFirst(f: (Item) -> Unit) = | |
when (this) { | |
is Empty -> Unit | |
is Item -> f(this) | |
is ItemStack -> f(this.items.first()) | |
} | |
} | |
object Empty : Elem() { | |
override fun plus(e: Elem): Elem = e | |
} | |
data class Item(val obj: GameObject) : Elem() { | |
override fun plus(el: Elem): Elem = | |
when (el) { | |
is Empty -> this | |
is Item -> ItemStack(setOf(this, el)) | |
is ItemStack -> ItemStack(el.items + this) | |
} | |
} | |
data class ItemStack(val items: Set<Item>) : Elem() { | |
init { | |
require(items.size > 1) { "Stacks must contain > 1 items" } | |
} | |
override fun plus(el: Elem): Elem = | |
when (el) { | |
is Empty -> this | |
is Item -> ItemStack(this.items + el) | |
is ItemStack -> ItemStack(this.items + el.items) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment