「型の分離」(ユニオン型)を定義するにはどうすればいいですか? 質問する

「型の分離」(ユニオン型)を定義するにはどうすればいいですか? 質問する

一つの方法は提案されたオーバーロードされたメソッドの二重定義に対処するには、オーバーロードをパターンマッチングに置き換えます。

object Bar {
   def foo(xs: Any*) = xs foreach { 
      case _:String => println("str")
      case _:Int => println("int")
      case _ => throw new UglyRuntimeException()
   }
}

このアプローチでは、引数の静的型チェックを放棄する必要がありますfoo。次のように記述できれば、はるかに便利です。

object Bar {
   def foo(xs: (String or Int)*) = xs foreach {
      case _: String => println("str")
      case _: Int => println("int")
   }
}

で近づけますEitherが、2 種類以上になるとすぐに醜くなります。

type or[L,R] = Either[L,R]

implicit def l2Or[L,R](l: L): L or R = Left(l)
implicit def r2Or[L,R](r: R): L or R = Right(r)

object Bar {
   def foo(xs: (String or Int)*) = xs foreach {
      case Left(l) => println("str")
      case Right(r) => println("int")
   }
}

Either3一般的な (エレガントで効率的な) ソリューションでは、、、 ...を定義する必要があるようですEither4。同じ目的を達成するための別のソリューションを知っている人はいますか? 私の知る限り、Scala には組み込みの「型分離」はありません。また、上記で定義した暗黙の変換は、標準ライブラリのどこかに潜んでいて、インポートするだけでよいのでしょうか?

ベストアンサー1

マイルズ・セイビンは最近のブログ記事で、ユニオン型を取得する非常に良い方法を説明しています。Scala の Curry-Howard 同型性による非ボックス化共用体型:

彼はまず型の否定を次のように定義する。

type ¬[A] = A => Nothing

ド・モルガンの法則を使うと、ユニオン型を定義することができる。

type ∨[T, U] = ¬[¬[T] with ¬[U]]

以下の補助構造により

type ¬¬[A] = ¬[¬[A]]
type |∨|[T, U] = { type λ[X] = ¬¬[X] <:< (T ∨ U) }

ユニオン型は次のように記述できます。

def size[T : (Int |∨| String)#λ](t : T) = t match {
    case i : Int => i
    case s : String => s.length
}

おすすめ記事