Generics scala类型匹配

Generics scala类型匹配,generics,scala,pattern-matching,Generics,Scala,Pattern Matching,我想写一个通用方法来获取字符串或Int的x位置的元素。 现在我的问题是,如何强制Scala将T转换为Int或调用特定于Int的方法 代码如下: def key[T](elm:T,pos:Int) = elm match{ case x:Int => { def digit(number:Int, pos:Int):Int = { if(pos == 0) number % 10 else digit(number/10, pos-1) }

我想写一个通用方法来获取字符串或Int的x位置的元素。 现在我的问题是,如何强制Scala将T转换为Int或调用特定于Int的方法

代码如下:

def key[T](elm:T,pos:Int) = elm match{
  case x:Int => {
    def digit(number:Int, pos:Int):Int = {
      if(pos == 0) number % 10
        else digit(number/10, pos-1)
    }
    digit(elm.toInt,(elm.toInt).length-pos-1)
  } 
  case x:String => (elm.toString).charAt(pos)
}
谢谢

def key[T](elm:T,pos:Int) = elm match {
  case x:Int => {
    def digit(number:Int, pos:Int):Int = {
      if(pos == 0) number % 10
        else digit(number/10, pos-1)
      }
    digit(x,x.length-pos-1)
  } 
  case x:String => x.charAt(pos)
}
使用视图的解决方案:

implicit def i2s(i:Int):String = i.toString
def key2[T <% String](elm:T,pos:Int) = elm match { 
  case x:Int => x.charAt(pos) 
  case s:String => s.charAt(pos) 
}
implicit def i2s(i:Int):String=i.toString
def键2[T x.字符(位置)
大小写s:String=>s.charAt(pos)
}

我想说,您的问题是,您有两种类型需要对其进行操作,一种是Int,一种是String,您希望对该输入执行一个键方法,但您没有指定要返回的内容

我对Int的第一个想法是返回一个Int.toString().charAt(n)似乎是一种欺骗,但也许欺骗是可以的,所以让我们开始欺骗:

def cheat (a: Any, n: Int) = a.toString ().charAt (n) 
cheat (2345, 2) 
// res414: Char = 4
cheat ("foobar", 2) 
// res415: Char = o
这很好也很简单,不是吗?但是,如果你想为Int的输入返回Int,为String的输入返回String呢?对于String类型的输入,Char似乎更自然,一个字节就足以返回0-9之间的数字,但是如果我们为t返回t,我们有一个更简单的类型依赖关系

我不相信我的解决方案,但我不相信作弊,第一种解决方案只是一种更复杂的作弊方式,不是吗

class Atti [T] (val fun: (Int => T)) {
  def at (n: Int): T = fun (n) 
}
我定义了一个atti类,对于类型T,它需要一个函数,它接受一个Int,并返回一个T,如果在这个类上调用
at
,它将调用该函数

现在我们定义一个函数iGet,从一个整数中得到位置n处的数字,我们使用两个参数列表

def iGet (i: Int) (n: Int) : Int = {
  if (n == 0) i % 10
    else iGet (i / 10)(n - 1) }
…要传递Int,迫切需要对其进行操作以定义部分定义的函数:

val iAt = new Atti[Int] (iGet (2345) _)
 (0 to 3).map (iAt.at (_))
// res412: scala.collection.immutable.IndexedSeq[Int] = Vector(5, 4, 3, 2)
字符串的模拟函数和sAt声明:

def sGet (s: String) (n: Int) : String = "" + s.charAt (n)

val sAt = new Atti[String] (sGet ("foobar") _) 
 (0 to 3).map (sAt.at (_))
// res413: scala.collection.immutable.IndexedSeq[String] = Vector(f, o, o, b)
我猜您会看到字符串是从左到右求值的,而Int是从右到左求值的,就像您对问题的介绍一样

我不喜欢我自己的是,与有效载荷“foobar”在一起的不再是字符串,2345不知何故隐藏在iAt对象中

需要为每个字符串指定用于字符串的函数-这给了您比您要求的更大的灵活性,并为每个实例提供了更多的工作

我试图构建一个trait并将其混合到Int或String中,但没有成功:

trait Key [T] { def at (n: Int): T }
val s : String with Key[String] = "Foobar" { def at (n: Int) : String = "" + s.charAt (n) }  
<console>:7: error: type mismatch;
 found   : Unit
 required: Int
       val s : String with Key[String] = "Foobar" { def at (n: Int) : String = "" + s.charAt (n) }
                                                                                                 ^
trait Key[T]{def at(n:Int):T}
val s:String,键为[String]=“Foobar”{def at(n:Int):String=”“+s.charAt(n)}
:7:错误:类型不匹配;
发现:单位
必填项:Int
val s:String,键为[String]=“Foobar”{def at(n:Int):String=”“+s.charAt(n)}
^
如何强制Scala将T转换为 Int

你不能。你可以用一些隐式检查,但这比你必须做的要困难得多。不要使用
elm
,而是使用
x

def key[T](elm:T,pos:Int) = elm match{
  case x:Int => {
    def digit(number:Int, pos:Int):Int = {
      if(pos == 0) number % 10
        else digit(number/10, pos-1)
    }
    digit(x,x.toString.length-pos-1)
  } 
  case x:String => x.charAt(pos)
}

同样的问题:值length不是Int-digit(x,x.length-pos-1)Duh的成员。
length
不是Int的方法,但可以取对数(以10为底)为了达到这个目的,Int没有length方法。啊,酷,这是可行的:)但我的问题仍然存在。我如何强迫scala认为elm是Int类型的,这样我就可以调用elm.length方法?第二个解决方案也可以使用x.length,而不是x.charAt,以防你想要递归地找到答案。x是elm,但viewed作为一个Int。
def key[T](elm:T,pos:Int) = elm match{
  case x:Int => {
    def digit(number:Int, pos:Int):Int = {
      if(pos == 0) number % 10
        else digit(number/10, pos-1)
    }
    digit(x,x.toString.length-pos-1)
  } 
  case x:String => x.charAt(pos)
}