соответствие типа скалы - PullRequest
3 голосов
/ 15 мая 2011

Я хочу написать универсальный метод, чтобы получить элемент в позиции x строки или Int. Теперь мой вопрос: как я могу заставить 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)
}

Спасибо!

Ответы [ 4 ]

2 голосов
/ 15 мая 2011
def key[T](elm:T,pos:Int) = elm match { 
    case x:Int => x.toString.charAt(pos) 
    case s:String => s.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) 
}
1 голос
/ 15 мая 2011

Я бы сказал, ваша проблема в том, что у вас есть два типа, над которыми вы хотите работать: 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?Char кажется более естественным для ввода типа String, и байта будет достаточно, чтобы вернуть цифру от 0 до 9, но у нас будет более простая зависимость от типа, если мы вернем T для T.

IЯ не убежден в своем решении, но я не убежден в мошенничестве, и первые решения - это только более сложный способ мошенничества, не так ли?

class Atti [T] (val fun: (Int => T)) {
  def at (n: Int): T = fun (n) 
}

Я определил класс atti, который для типа T нуждается в функции, которая принимает Int и возвращает T, и если вы вызовете at для этого класса, он вызоветэта функция.

Теперь мы определяем функцию iGet, чтобы получить из Int цифру в позиции 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 - справа налево, как в вашем введении в проблему.

Мне не нравится то, что sAt с полезной нагрузкой 'foobar' неСтрока больше, и 2345 каким-то образом скрыт в iAt-объекте.

И функцию, которую следует использовать для строки, необходимо указывать для каждой строки, что дает вам большую гибкость, чем вы просили, и больше работы для каждого экземпляра.

Я пытался создать черту и смешать ее с 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) }
                                                                                                 ^
0 голосов
/ 15 мая 2011

как заставить 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)
}
0 голосов
/ 15 мая 2011
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)
}
...