Skip to content

Instantly share code, notes, and snippets.

@HusrevAtSky
Forked from jrudolph/TowersOfHanoi.scala
Last active August 23, 2022 14:38
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save HusrevAtSky/cae020c79c844e22024c8cd027a5c6ce to your computer and use it in GitHub Desktop.
Save HusrevAtSky/cae020c79c844e22024c8cd027a5c6ce to your computer and use it in GitHub Desktop.
Scala-Metaprogramming: Towers of Hanoi
import shapeless.ops.hlist.Prepend
import shapeless.{::, HList, HNil, Nat, Succ}
object Hanoi {
// influenced by : https://gist.github.com/jrudolph/66925
// in action : https://youtu.be/mc6c_sX-ESc
case class Left()
case class Center()
case class Right()
case class Move[N<:Nat,A,B,C,History <: HList]()
implicit def move0[A,B,C]:Move[Nat._1,A,B,C, (A,B) :: HNil] = {
null
}
implicit def moveN[P<:Nat,A,B,C, H1 <: HList, H2 <: HList, H3 <: HList, H2andH3<:HList, Out <: HList]
(implicit m1:Move[P,A,C,B, H1],
m2:Move[Nat._1,A,B,C,H2],
m3:Move[P,C,B,A,H3],
prependH2andH3: Prepend.Aux[H2,H3, H2andH3],
prepend: Prepend.Aux[H1,H2andH3, Out])
:Move[Succ[P],A,B,C, Out] = null
def run[N<:Nat,A,B,C,H <: HList](n: N, a: A, b: B, c: C)(implicit m:Move[N,A,B,C,H]) : H = null.asInstanceOf[H]
val a = run(new Nat._3, Left(), Right(), Center())
// type is calculated by intellj as
// val a: ::[(Left, Right), HNil] = run(new Nat._1, Left(), Right(), Center())
// val b: ::[(Left, Center), ::[(Left, Right), ::[(Center, Right), HNil]]] = run(new Nat._2, Left(), Right(), Center())
// val c: ::[(Left, Right), ::[(Left, Center), ::[(Right, Center), ::[(Left, Right), ::[(Center, Left), ::[(Center, Right), ::[(Left, Right), HNil]]]]]]] = run(new Nat._3, Left(), Right(), Center())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment