1. ホーム
  2. scala

[解決済み] 型の論理和(ユニオン型)はどのように定義するのですか?

2022-04-13 04:15:26

質問

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

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には組み込みの"型分離関数"がありません。また、上で定義した暗黙の変換は、標準ライブラリのどこかに潜んでいて、それをインポートすればいいのでしょうか?

どのように解決するのですか?

さて、具体的な事例としては Any* というのも、混合型を受け付けないからです。しかし、混合型はオーバーロードでも動作しないので、これはあなたが望むことかもしれません。

まず、以下のように受け入れたい型を持つクラスを宣言します。

class StringOrInt[T]
object StringOrInt {
  implicit object IntWitness extends StringOrInt[Int]
  implicit object StringWitness extends StringOrInt[String]
}

次に foo このように

object Bar {
  def foo[T: StringOrInt](x: T) = x match {
    case _: String => println("str")
    case _: Int => println("int")
  }
}

で、終わりです。を呼び出すことができます。 foo(5) または foo("abc") で、うまくいくのですが、試しに foo(true) となり、失敗します。これは、クライアントコードが StringOrInt[Boolean] で指摘されているように ランドール を作成します。 StringOrInt a sealed クラスがあります。

という理由で動作します。 T: StringOrInt という型の暗黙のパラメータがあることを意味します。 StringOrInt[T] Scalaはある型のコンパニオンオブジェクトの内部を調べて、その型を求めるコードが動作するように暗黙の了解があるかどうかを確認するからです。