This file contains 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 shapeless.{::, HList, HNil} | |
import io.estatico.newtype.macros.newtype | |
object Program { | |
type EntityState = | |
Map[EID,Name] :: | |
Map[EID,Might] :: | |
Map[EID,Magic] :: | |
Map[EID,Hp] :: | |
HNil | |
@newtype case class EID(toInt: Int) | |
@newtype case class Name(toStr: String) | |
@newtype case class Might(toInt: Int) | |
@newtype case class Magic(toInt: Int) | |
@newtype case class Hp(toInt: Int) | |
trait Setter[A,B,K] { | |
def set(k: K)(b: B)(a: A): A | |
} | |
implicit def mapSetter[A,K]: Setter[Map[K,A],A,K] = new Setter[Map[K,A],A,K] { | |
def set(k: K)(a: A)(m: Map[K,A]): Map[K,A] = m + (k -> a) | |
} | |
implicit def headSetter[H, T <: HList, K, A](implicit ev: Setter[H,A,K]): Setter[H :: T, A, K] = new Setter[H :: T, A, K] { | |
def set(k: K)(a: A)(xs: H :: T): H :: T = ev.set(k)(a)(xs.head) :: xs.tail | |
} | |
implicit def tailSetter[X, T <: HList, K, A](implicit ev: Setter[T,A,K]): Setter[X :: T, A, K] = new Setter[X :: T, A, K] { | |
def set(k: K)(a: A)(xs: X :: T): X :: T = xs.head :: ev.set(k)(a)(xs.tail) | |
} | |
def saveValue[A,K,H <: HList](k: K)(a: A)(xs: H)(implicit ev: Setter[H,A,K]): H = ev.set(k)(a)(xs) | |
trait Merger[A,B,K] { | |
def merge(k: K)(a: A)(b: B): B | |
} | |
implicit def nilMErger[I <: HList, K]: Merger[HNil,I,K] = new Merger[HNil, I, K] { | |
def merge(k: K)(h: HNil)(i: I): I = i | |
} | |
implicit def headMerger[H <: HList, I <: HList, X, K](implicit ev: Setter[I,X,K], ev2: Merger[H,I,K]): Merger[X :: H,I,K] = new Merger[X :: H,I,K] { | |
def merge(k: K)(h: X :: H)(i: I): I = ev2.merge(k)(h.tail)(saveValue(k)(h.head)(i)) | |
} | |
def saveAll[H <: HList, I <: HList, K](k: K)(toSave: H)(model: I)(implicit ev: Merger[H,I,K]): I = ev.merge(k)(toSave)(model) | |
def main(args: Array[String]): Unit = { | |
val initial = | |
Map.empty[EID,Name] :: | |
Map.empty[EID,Might] :: | |
Map.empty[EID,Magic] :: | |
Map.empty[EID,Hp] :: | |
HNil | |
val result = saveValue(EID(1))(Name("Loreck"))(initial) | |
println(result) | |
val result2 = saveAll(EID(1))(Name("Loreck") :: Might(11) :: Magic(3) :: Hp(9) :: HNil)(initial) | |
println(result2) | |
// Not all need to be present | |
val result3 = saveAll(EID(1))(Name("Loreck") :: Might(11) :: Hp(9) :: HNil)(initial) | |
println(result3) | |
// Order doesn't matter | |
val result4 = saveAll(EID(1))(Hp(9) :: Might(11) :: Magic(3) :: HNil)(initial) | |
println(result4) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment