暗黙の型変換を考える(3)

型の中に式があるのではなくて、型と式のタプルに修正しました。
こんな感じで、式に対して、castを必要な箇所に挿入できるようになります。
これを、関数のある言語について拡張していければいいんでしょうが、
その為には環境を持ってうんぬんしないといけません。
関数まで出来たら、型推論を入れられると非常に嬉しいのですが、まだまだ先です。
型と式と式に型を付ける関数とcastを付ける関数で暗黙の型変換ができるということのようです。

object ttest {
  trait TType
  case class TFloat() extends TType
  case class TInt() extends TType
  case class TNone() extends TType

  trait T
  case class CastInt(a:T) extends T
  case class CastFloat(a:T) extends T
  case class Int(a:scala.Int) extends T
  case class Float(a:Double) extends T
  case class Add(a:T, b:T) extends T
  case class FAdd(a:T, b:T) extends T

  def main(argv:Array[String]) {
    println(t(Add(Float(1),Int(2))))
    println(t(Add(Int(1),Int(2))))
    println(t(Add(Add(Float(1),Int(1)),Int(2))))
  }

  def t(a:T):(TType,T) = a match {
    case Int(_) => (TInt(),a)
    case Float(_) => (TFloat(),a)
    case CastInt(_) => (TInt(),a)
    case CastFloat(_) => (TFloat(),a)
    case Add(a, b) =>
      ic(t(a), t(b)) match {
        case (TInt(), a, b) => (TInt(),Add(a,b))
        case (TFloat(), a, b) => (TFloat(),FAdd(a,b))
      }
    case FAdd(a,b) => t(Add(a,b))
  }

  def ic(a:(TType,T), b:(TType,T)):(TType,T,T) = (a,b) match {
    case ((TFloat(),a), (TFloat(),b)) => (TFloat(),a,b)
    case ((TFloat(),a), (_,b)) => (TFloat(),a,CastFloat(b))
    case ((_,a), (TFloat(),b)) => (TFloat(),CastFloat(a), b)
    case ((TInt(),a), (TInt(),b)) => (TInt(),a,b)
    case ((TInt(),a), (_,b)) => (TInt(),a,CastInt(b))
    case ((_,a), (TInt(),b)) => (TInt(),CastInt(a),b)
  }
}