[SCALA] 스칼라 : 어떻게 "일반적인"기능 매개 변수를 정의?
SCALA스칼라 : 어떻게 "일반적인"기능 매개 변수를 정의?
나는 하스켈의 경험을 조금을 현재 스칼라를 배우려고 노력하고 있습니다. 하스켈이 필요하지 않습니다 - 뭔가 나에게 이상한로서 밖으로 서 한 가지 스칼라의 모든 기능 매개 변수 유형 주석해야한다는 것입니다. 왜 이런거야? 좀 더 구체적인 예로서 넣어 시도하려면 추가 기능은 다음과 같이 기록됩니다
def add(x:Double, y:Double) = x + y
그러나, 복식이 유일한 작품 (물론, int 치의 때문에 암시 적 타입 변환의 너무 일). 하지만 당신이 원한다면 것은 자신의 + 연산자를 정의 자신의 유형을 정의합니다. 어떻게 당신은 + 연산자를 정의하는 모든 유형의 작동하는 추가 기능을 작성합니다?
해결법
-
==============================
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.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.하스켈은 힌들리 - 밀너의 형식 유추를 사용합니다. 타입 추론의이 종류는 강력하지만 언어의 타입 시스템을 제한합니다. 기발한 예를 들어, 서브 클래스는 H-M과 잘 작동하지 않습니다.
하스켈은 힌들리 - 밀너의 형식 유추를 사용합니다. 타입 추론의이 종류는 강력하지만 언어의 타입 시스템을 제한합니다. 기발한 예를 들어, 서브 클래스는 H-M과 잘 작동하지 않습니다.
여하튼, 스칼라 타입 시스템은 H-M 너무 강력하므로 타입 추론보다 한정된 종류가 사용되어야한다.
-
==============================
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.기능 자체는 매우 간단합니다 :
기능 자체는 매우 간단합니다 :
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 = { ... } ... }
그것은 당신이 지금 당장 알고 싶어보다 더 할 수 있지만 모두가 어떻게 일반적인 인수와이를 실현하는 방법을 정의하는 방법 보여 않습니다.
궁극적으로, 특정 유형은 필요하지 않지만 컴파일러는 적어도 형식의 경계를 알 필요가 없습니다.
from https://stackoverflow.com/questions/1252915/scala-how-to-define-generic-function-parameters by cc-by-sa and MIT license
'SCALA' 카테고리의 다른 글
[SCALA] 나는 스칼라에 밀봉 부모로부터 파생 케이스의 모든 개체의 컴파일 시간 목록을받을 수 있습니까? (0) | 2019.11.03 |
---|---|
[SCALA] 어떻게 22 개 필드의 스칼라 경우 클래스의 제한을 극복하기 위해? (0) | 2019.11.03 |
[SCALA] _ * 스칼라의 의미 : 무슨 일이 PARAM은 무엇입니까? (0) | 2019.11.03 |
[SCALA] 스칼라에 대한 JVM 힙 크기를 증가? (0) | 2019.11.03 |
[SCALA] 스파크 : 단일 키 RDD와 2 튜플 키 RDD 가입을위한 최선의 전략은 무엇입니까? (0) | 2019.11.03 |