2016-11-06 1 views
1

Я довольно новичок в Scala после работы с Java некоторое время, поэтому прошу прощения, если это основной вопрос. У меня есть метод, который я хотел бы запускать как с плавающей, так и с двойной точностью, и казалось, что это довольно легко сделать с полиморфизмом Scala. В Java единственный способ, которым я нашел это, - перегрузка метода и наличие одного аргумента float, а другое - двойные аргументы, но я надеюсь, что полиморфизм позволит мне избежать этого и просто иметь один метод, который будет работать либо с. Образом я реализовал это до сих пор выглядит следующим образом (https://stackoverflow.com/a/4033390/6247850, как сделать общие операции работы между аргументами):Преобразование типа Scala в полиморфном методе

def Sample[A: Numeric](x: A, y: A)(implicit num: Numeric[A]): A= { 
    import num._ 
    var out = 2.0.asInstanceOf[A] * x * y 
    return out 
} 

Это прекрасно работает с двойной точностью, но приводит к ClassCastException, если я пытаюсь запустить это в Float. Я могу жестко установить обходной путь, изменив его на 2.0.toFloat.asInstanceOf[A], что заставляет меня думать, что должен быть какой-то способ сделать это, но жесткое кодирование, как это, наносит ущерб тому, чтобы сделать его общим. Я также должен был сделать то, что казалось непропорциональным объемом работы, чтобы заставить подразделение работать правильно, используя этот ответ https://stackoverflow.com/a/34977463/6247850 и построив его, чтобы получить меньше, чем сравнение для работы.

По сути, я хочу, чтобы указать точность, с которой должен работать метод и вернуться. Проблема связана с тем, что другие переменные, используемые в методе, относятся к соответствующему типу, поскольку .asInstanceOf[A] не работает, если он уже не был правильным.

ответ

3

Вот краткое решение с использованием методов из Numeric в явном виде:

def Sample[A: Numeric](x: A, y: A)(implicit num: Numeric[A]): A = { 
    num.times(
    num.fromInt(2), 
    num.times(x, y) 
) 
} 

Это позволяет первым разрешить все неясности с перегруженными арифметическими операторами. Фактический ключ здесь был использованием метода fromInt, так что мы можем написать его короче (так же, как в вашем коде) с операторами снова:

def Sample[A: Numeric](x: A, y: A)(implicit num: Numeric[A]): A = { 
    import num._ 
    fromInt(2) * x * y 
} 

Вам не нужен никакая отливки здесь (в данном конкретном примере) , Вот использование демо:

scala> Sample(2.5D, 0.01D) 
res12: Double = 0.05 

scala> Sample(2.5F, 0.01F) 
res13: Float = 0.049999997 

Что касается более общей ситуации, когда просто некоторое количество вместо 2 и вы не знаете, какой тип вы хотите, чтобы это было заранее, я думаю, вы не можете решить с только одна полиморфная функция. Вы можете определить typeclass и предоставить неявные экземпляры для определенных типов, с которыми вы хотите работать (ad-hoc polymorphism).

+0

Вау, спасибо за быстрый ответ! Есть ли способ сделать его более кратким при одновременном использовании большого количества операций? Код типа 'num.times (num.fromInt (2), num.times (x, num.plus (num.fromInt (1), y)))' действительно трудно читать по сравнению с '2 * x * (1 + y) ' – user6247850

+0

@ пользователь6247850 на самом деле да, только в вашем исходном коде. Я добавлю эту альтернативу. Также см. Мое обновление об общем случае. – laughedelic