Я думаю в ГРУШЕВОЙ документации, существует рекомендация для, требуют, require_once, включают и include_once. Я действительно следую той инструкции. Ваше приложение было бы более четким.
Haskell использует алгоритм вывода типа Хиндли-Милнера, тогда как Scala, чтобы поддерживать объектно-ориентированную сторону вещей, на данный момент вынужден был отказаться от его использования.
Чтобы легко написать функцию добавления для всех применимых типов, вам понадобится Scala 2.8.0:
Welcome to Scala version 2.8.0.r18189-b20090702020221 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_15).
Type in expressions to have them evaluated.
Type :help for more information.
scala> import Numeric._
import Numeric._
scala> def add[A](x: A, y: A)(implicit numeric: Numeric[A]): A =
| numeric.plus(x, y)
add: [A](x: A,y: A)(implicit numeric: Numeric[A])A
scala> add(1, 2)
res0: Int = 3
scala> add(1.1, 2.2)
res1: Double = 3.3000000000000003
Сама функция будет будьте довольно прямолинейны:
def add(x: T, y: T): T = ...
А еще лучше, вы можете просто перегрузить метод +:
def +(x: T, y: T): T = ...
Однако здесь отсутствует часть, которая является самим параметром типа. Как написано, у метода отсутствует свой класс. Скорее всего, вы
Haskell использует вывод типа Хиндли-Милнера . Этот вид вывода типов является мощным, но ограничивает систему типов языка. Предположительно, например, создание подклассов плохо работает с HM.
В любом случае, система типов Scala слишком мощна для HM, поэтому необходимо использовать более ограниченный вид вывода типов.
Я думаю, что причина, по которой Scala требует аннотации типа для параметров вновь определенной функции, исходит из того факта, что Scala использует более локальный анализ вывода типов, чем тот, что используется в Haskell.
Если все ваши классы смешаны в признаке, скажем Addable [T]
, который объявил оператор +
, вы можете написать свою общую функцию добавления как:
def add[T <: Addable[T]](x : T, y : T) = x + y
Это ограничивает функцию добавления до типы T, которые реализуют признак Addable
К сожалению, в текущих библиотеках Scala такой особенности нет. Но вы можете увидеть, как это было бы сделано, посмотрев на аналогичный случай - черту Ordered [T]
. Эта черта объявляет операторы сравнения и смешивается с классами RichInt
, RichFloat
и т. Д. Затем вы можете написать функцию сортировки, которая может принимать, например, a Список [T]
, где [T <: Ordered [T]]
для сортировки списка элементов, которые смешиваются в упорядоченном признаке. Из-за неявного преобразования типов, например Float
в RichFloat
, вы даже можете использовать функцию сортировки в списках Int
или Float
или Double
.
Как я уже сказал, к сожалению, для оператора +
нет соответствующей черты. Значит, вам придется все выписывать самому. Вы должны использовать трейт Addable [T], создать AddableInt
, AddableFloat
и т. Д., Классы, расширяющие Int, Float и т. Д., И смешать трейт Addable, и, наконец, добавить неявный функции преобразования для преобразования, например, и Int в AddableInt
,
Чтобы укрепить концепцию использования неявного для себя, я написал пример, который не требует scala 2.8, но использует ту же концепцию. Я подумал, что это может быть полезно для некоторых. Сначала вы определяете обобщенно-абстрактный класс Addable :
scala> abstract class Addable[T]{
| def +(x: T, y: T): T
| }
defined class Addable
Теперь вы можете написать функцию add следующим образом:
scala> def add[T](x: T, y: T)(implicit addy: Addable[T]): T =
| addy.+(x, y)
add: [T](T,T)(implicit Addable[T])T
Это используется как класс типов в Haskell. Затем, чтобы реализовать этот универсальный класс для определенного типа, вы должны написать (примеры здесь для Int, Double и String):
scala> implicit object IntAddable extends Addable[Int]{
| def +(x: Int, y: Int): Int = x + y
| }
defined module IntAddable
scala> implicit object DoubleAddable extends Addable[Double]{
| def +(x: Double, y: Double): Double = x + y
| }
defined module DoubleAddable
scala> implicit object StringAddable extends Addable[String]{
| def +(x: String, y: String): String = x concat y
| }
defined module StringAddable
На этом этапе вы можете вызвать функцию add с все три типа:
scala> add(1,2)
res0: Int = 3
scala> add(1.0, 2.0)
res1: Double = 3.0
scala> add("abc", "def")
res2: java.lang.String = abcdef
Конечно, не так хорош, как Haskell, который, по сути, сделает все это за вас. Но в этом и заключается компромисс.