복붙노트

[SCALA] 스칼라 : 어떻게 "일반적인"기능 매개 변수를 정의?

SCALA

스칼라 : 어떻게 "일반적인"기능 매개 변수를 정의?

나는 하스켈의 경험을 조금을 현재 스칼라를 배우려고 노력하고 있습니다. 하스켈이 필요하지 않습니다 - 뭔가 나에게 이상한로서 밖으로 서 한 가지 스칼라의 모든 기능 매개 변수 유형 주석해야한다는 것입니다. 왜 이런거야? 좀 더 구체적인 예로서 넣어 시도하려면 추가 기능은 다음과 같이 기록됩니다

def add(x:Double, y:Double) = x + y

그러나, 복식이 유일한 작품 (물론, int 치의 때문에 암시 적 타입 변환의 너무 일). 하지만 당신이 원한다면 것은 자신의 + 연산자를 정의 자신의 유형을 정의합니다. 어떻게 당신은 + 연산자를 정의하는 모든 유형의 작동하는 추가 기능을 작성합니다?

해결법

  1. ==============================

    1.하스켈 사물의 객체 지향 측면을 지원하기 위해, 스칼라 반면 힌들리 - 밀너 타입 추론 알고리즘을 사용하여, 지금은 그것을 사용 포기했다.

    하스켈 사물의 객체 지향 측면을 지원하기 위해, 스칼라 반면 힌들리 - 밀너 타입 추론 알고리즘을 사용하여, 지금은 그것을 사용 포기했다.

    쉽게 적용 가능한 모든 유형의 추가 기능을 쓰기 위해서는 스칼라 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
    
  2. ==============================

    2.자신에 대한 암시 적 사용의 개념을 공고히하기 위해, 나는 스칼라 2.8을 필요로하지 않습니다 예를 썼다,하지만 같은 개념을 사용한다. 나는 약간의 도움이 될 수있다 생각했다. 첫째, 당신은 일반적인-추상 클래스 한 Addable를 정의합니다 :

    자신에 대한 암시 적 사용의 개념을 공고히하기 위해, 나는 스칼라 2.8을 필요로하지 않습니다 예를 썼다,하지만 같은 개념을 사용한다. 나는 약간의 도움이 될 수있다 생각했다. 첫째, 당신은 일반적인-추상 클래스 한 Addable를 정의합니다 :

    scala> abstract class Addable[T]{
     |   def +(x: T, y: T): T
     | }
    defined class Addable
    

    지금 당신은이 같은 추가 기능을 쓸 수 있습니다 :

    scala> def add[T](x: T, y: T)(implicit addy: Addable[T]): T = 
     | addy.+(x, y)
    add: [T](T,T)(implicit Addable[T])T
    

    이는 하스켈 타입 클래스처럼 사용된다. 그런 다음 (INT, 더블 및 문자열 여기 예)를 작성합니다, 특정 타입에 대해,이 제네릭 클래스를 실현하기 :

    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
    

    이 시점에서 당신은 세 가지 유형의 추가 함수를 호출 할 수 있습니다 :

    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
    

    물론 당신이 모든 하스켈만큼 좋은 할 본질적으로하지 않습니다있다. 트레이드 오프가 자리하고있는 곳입니다하지만, 그건.

  3. ==============================

    3.하스켈은 힌들리 - 밀너의 형식 유추를 사용합니다. 타입 추론의이 종류는 강력하지만 언어의 타입 시스템을 제한합니다. 기발한 예를 들어, 서브 클래스는 H-M과 잘 작동하지 않습니다.

    하스켈은 힌들리 - 밀너의 형식 유추를 사용합니다. 타입 추론의이 종류는 강력하지만 언어의 타입 시스템을 제한합니다. 기발한 예를 들어, 서브 클래스는 H-M과 잘 작동하지 않습니다.

    여하튼, 스칼라 타입 시스템은 H-M ​​너무 강력하므로 타입 추론보다 한정된 종류가 사용되어야한다.

  4. ==============================

    4.나는 스칼라가 새롭게 정의 된 함수의 매개 변수에 대한 형식 주석을 필요로하는 이유는 스칼라는 하스켈에 사용 된 것보다 더 많은 지역 형식 유추 분석을 사용한다는 사실에서 유래 생각합니다.

    나는 스칼라가 새롭게 정의 된 함수의 매개 변수에 대한 형식 주석을 필요로하는 이유는 스칼라는 하스켈에 사용 된 것보다 더 많은 지역 형식 유추 분석을 사용한다는 사실에서 유래 생각합니다.

    모든 클래스가 특성에 혼합하면, + 연산자를 선언 한 Addable [T]를, 당신이 당신의 일반적인 부가 기능 등을 쓸 수 있다고 말한다 :

    def add[T <: Addable[T]](x : T, y : T) = x + y
    

    이것은 한 Addable 특성을 구현하는 유형 T에 추가 기능을 제한합니다.

    불행하게도, 현재 스칼라 라이브러리 이러한 특성은 없다. 그러나 당신은이 비슷한 경우, 정렬 식 [T]의 특성을보고 할 것입니다 방법을 볼 수 있습니다. 이 특성은 비교 연산자를 선언 등 클래스입니다 RichInt, RichFloat에 의해 혼합되어있다. 주문한 특성에 혼합 요소 목록을 정렬 : 그럼 당신은 예를 들어, 취할 수있는 정렬 기능, [정렬 된 [T]를 T <] 목록 [T]를 쓸 수 있습니다. 때문에 RichFloat에 플로트 같은 암시 적 형식 변환, 당신은 심지어 지능의 목록에 정렬 ​​기능을 사용하거나 플로트 또는 더블 수 있습니다.

    말했듯이, 불행하게도, + 연산자에 대한 대응하는 특성이 없다. 그래서, 당신은 모든 것을 스스로를 작성해야합니다. 당신은 등 AddableInt, AddableFloat 등 지능을 확장하는 클래스, 플로트를 만듭니다 한 Addable [T] 특성을하고 한 Addable 특성에 혼합, 그리고 마지막으로에 암시 적 변환 설정하는 기능, 예를 들어, 및 지능을 추가 AddableInt는, 컴파일러는 인스턴스화하고 그것으로 당신의 추가 기능을 사용할 수 있도록.

  5. ==============================

    5.기능 자체는 매우 간단합니다 :

    기능 자체는 매우 간단합니다 :

    def add(x: T, y: T): T = ...
    

    더 나은 아직, 당신은 단지 + 방법을 과부하 수 있습니다 :

    def +(x: T, y: T): T = ...
    

    누락 된 부분은 형식 매개 변수 자체이다, 그러나,있다. 기록으로, 메소드는 클래스가 없습니다. 가능성이 가장 높은 경우는, T의 인스턴스에 + 메소드를 호출 최근에 그것을 내가 이런 짓을 T.의 다른 인스턴스를 전달 말했다 특성을 정의하고 있다는 것입니다, "첨가제 그룹은 추가 작업으로 구성 플러스 수단 요소를 "반전

    trait GroupAdditive[G] extends Structure[G] {
      def +(that: G): G
      def unary_- : G
    }
    

    그런 후, 나는 그 자체 (필드 GroupAdditive를 확장)의 인스턴스를 추가하는 방법을 알고있는 실제 클래스를 정의 :

    class Real private (s: LargeInteger, err: LargeInteger, exp: Int) extends Number[Real] with Field[Real] with Ordered[Real] {
      ...
    
      def +(that: Real): Real = { ... }
    
      ...
    }
    

    그것은 당신이 지금 당장 알고 싶어보다 더 할 수 있지만 모두가 어떻게 일반적인 인수와이를 실현하는 방법을 정의하는 방법 보여 않습니다.

    궁극적으로, 특정 유형은 필요하지 않지만 컴파일러는 적어도 형식의 경계를 알 필요가 없습니다.

  6. from https://stackoverflow.com/questions/1252915/scala-how-to-define-generic-function-parameters by cc-by-sa and MIT license