This is the code for the blog entry Meta-Programming with Scala Part III: Partial function application
package michid.meta
object Metamult {
// Church encoding of natural numbers
type _0[s[_], z] = z
type _1[s[_], z] = s[z]
type _2[s[_], z] = s[s[z]]
type _3[s[_], z] = s[s[s[z]]]
trait curry[n[_[_], _], s[_]] {
type f[z] = n[s, z]
}
// Multiplication for this encoding
type mult[m[_[_], _], n[_[_], _], s[_], z] = m[curry[n, s]#f, z]
abstract class Zero
abstract class Succ[T]
// Use of infix notation for more convinient syntax
type x[m[_[_], _], n[_[_], _]] = mult[m, n, Succ, Zero]
// See http://michid.wordpress.com/2008/03/12/puzzle-the-depth-of-a-type-solution/
def value[T] = null.asInstanceOf[T];
trait Rep[T] {
def eval: Int
}
implicit def toRep0(n: Zero) = new Rep[Zero] {
def eval = 0
}
implicit def toRepN[T](n: Succ[T])(implicit f: T => Rep[T]) = new Rep[Succ[T]] {
def eval = f(value[T]).eval + 1
}
def main(args: Array[String]) {
println((value[_1 x _1]).eval) // prints 1
println((value[_1 x _2]).eval) // prints 2
println((value[_2 x _1]).eval) // prints 2
println((value[_2 x _2]).eval) // prints 4
println((value[_2 x _3]).eval) // prints 6
println((value[_3 x _2]).eval) // prints 6
println((value[_3 x _3]).eval) // prints 9
}
}