2016-11-08 3 views
1

のIntとChar型Scalaの補間(ジェネリックと上限)

だが、私はどちらか一方のみ期待するのInt次の関数を(持っているとしましょうまたはCHAR):

def foo[T](tuple: Tuple2[T, T]) = tuple match { 
    case Tuple2(x: Int, y: Int) => (x to y).toArray 
    case Tuple2(x: Char, y: Char) => (x to y).toArray 
} 

私のような、より良いと圧縮形式を持っていることを期待する:

​​

しかし、これは間違いなく動作していません。

アイデア?

+0

'T字型'の下界を「Char with Int」と呼んでいないのですか?それは何をしようとしていますか? –

+0

申し訳ありません、編集済みです。 – jalv1039

+1

あなたは私が思う組合タイプが欲しいです。 http://stackoverflow.com/questions/3508077/how-to-define-type-disjunction-union-types –

答えて

1

構文を使用するために必要なimplicitsと型の制約を整理しようとするのではなく、NumericRange.inclusiveを呼び出すほうが簡単です。暗黙的にIntegralが必要な場合は、範囲を1ステップで構成する方法を知ります(Integralインスタンスによって提供されます)。 (あなたは型制約を持つにそれらをしたい場合)

import scala.reflect.ClassTag 
import scala.collection.immutable.NumericRange 

def foo2[A >: Int with Char : ClassTag](tuple: (A, A))(implicit int: Integral[A]) = 
    NumericRange.inclusive(tuple._1, tuple._2, int.one).toArray 

scala> foo2(('a', 'z')) 
res13: Array[Char] = Array(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z) 

scala> foo2((1, 10)) 
res14: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 

その他の失敗:我々はまた、一般的にArrayを作成するClassTag[A]が必要になります

scala> foo2((1L, 10L)) 
<console>:19: error: could not find implicit value for parameter int: Integral[AnyVal] 
     foo2((1L, 10L)) 
     ^
+0

array [Int] = Array(1、2、3、4、5、6、7、8、9、10)を返す必要があります。 ' – jalv1039

+0

@ jalv1039代わりに' NumericRange.inclusive'を使うように更新しました。 –

2

はここでは使用することができ、比較的、恐ろしい署名ですそれを破壊

def foo[T 
    <% RangedProxy[T]{ type ResultWithoutStep <: TraversableOnce[T] } 
    : ClassTag 
](tup: (T, T)) 

:あなたの実装に(tup._1 to tup._2).toArray構文を取得する
をTは暗黙的にRangedProxy[T]に変換可能であり、toメソッドが定義されています。結果のタイプがtoの場合、タイプのメンバーResultWithoutStepに依存します。TraversableOnce[T]のサブクラスであることを確認してください。.toArrayを呼び出すことができます。

上記のシグネチャも@MichaelZajacの答えも、要求された機能が「IntとCharのみで動作する」ことはありません。実際には、それを満たすための最良の方法は、タイプキャストを使用することです。

sealed trait Fooable[T] extends ((T, T) => Array[T]) 
object Fooable { 
    private def impl[T](f: (T, T) => Array[T]) = 
    new Fooable[T]{ def apply(min: T, max: T): Array[T] = f(min, max) } 
    implicit val intFooable = impl[Int]{ (i,j) => (i to j).toArray } 
    implicit val charFooable = impl[Char]{ (a,b) => (a to b).toArray } 
} 
def foo[T: Fooable](tup: (T, T)) = implicitly[Fooable[T]].apply(tup._1, tup._2) 

残念ながら、型クラスのアプローチは、この特定の問題のために少し面倒ですが、implicit val xFooableに焦点を当てる場合は、それは次のように種類の似ていることがわかります:私は

// unfortunately this doesn't work due to type erasure on the JVM, 
// which is why we've resorted to typeclasses as above 
def foo(tup: (Int, Int)) = ... 
def foo(tup: (Char, Char)) = ... 
+0

'>:Int with Char'を鉱山に追加すると' Int'と 'Char'に制限されますが、' Integral'はクライアントコードが他の型を使用しないようにするため実際的な理由はありません。 –

関連する問題