2014-11-03 3 views
2

유형 별칭에서 스칼라로 객체를 구성하는 방법은 무엇입니까?스칼라의 유형 별칭에서 객체 만들기

type MyType = List[Int] 
println(List[Int]()) 
println(MyType()) // error: not found: value MyType 

이 유형의 새 인스턴스를 반환해야하는 함수에서는 문제가 있습니다. 기본 예제 :

def foo(x: MyType): MyType = { 
    if (x.head == 0) MyType() // Should Nil be used? 
    else if (x.head == -1) new MyType(1,2,3,4) 
    else x 
} 

방법 foo MyType의 실제 유형의 인식이 될 수 있습니까?

+0

당신은 내 대답이 당신이 요구 한 것을 제공한다는 것을 알지만, 당신이 선택한 대답은 그렇지 않습니다 ... 맞습니까? – Nate

+1

예 대답은 요청 된 명시적인 결과를 제공하지만, 그것이 어떻게 성취되었으며, 왜 필요한지에 대해서는 거의 설명하지 않습니다. 당신의 대답은 또한 왜 원하는 해결책이 가능하지 않은지에 대한 설명을 제공하지 않습니다. 아마도 나는 내 질문을 부적절하게 표현했다. 이 경우에 _why_는 _how_보다 더 관련이 있습니다. – cheezsteak

+0

귀하의 질문에 나타나지 않았거나 그렇지 않은 경우 답변을 드릴 수 없었습니다. 선택한 대답조차도 유형 대 동반자 객체의 패턴을 설명하지 않습니다. – Nate

답변

8

스칼라 (예 : Java)는 유형 및 값에 대해 다른 네임 스페이스를 가지며 유형 별칭은 유형 네임 스페이스에만 별칭을 도입합니다. 어떤 경우에는 당신이 당신이 찾고있는 효과를 얻을 수있는 동반자 개체를 참조하는 val로 별칭을 쌍을 수 있습니다, 이것은하지만, List[Int] 작동하지 않습니다

scala> case class Foo(i: Int) 
defined class Foo 

scala> type MyType = Foo 
defined type alias MyType 

scala> val MyType = Foo 
MyType: Foo.type = Foo 

scala> MyType(1) 
res0: Foo = Foo(1) 

가입일 동안 List 유형 모두와 List 동반자 개체의 apply 메서드는 형식 매개 변수가 있으며 List 동반 개체 자체는 없습니다.

가장 좋은 방법은 Nil: MyType과 같은 것을 사용하는 것이지만 일반적으로이 유형의 별칭 (예 : 약어)을 사용하면 종종 가장 좋은 해결책이 아님을 알 수 있습니다.

+0

'val MyType = List'의 문제점은 무엇입니까? 그렇다면'MyType [Int]()'는'MyType.apply [Int]()'와 desugar 될 것이며 모두가 행복합니다 ... – gzm0

+0

@ gzm0 :'MyList'를 일반용 (용어 용)으로 지정하고 'Int'(유형 용)에 고유하게 지정하면 나에게 혼란을 일으키는 제조법처럼 보입니다. –

+0

아, 그래. 나는 틀린 것을 보았다. 별칭이 더 높다고 생각했다. 죄송합니다. – gzm0

1

잘못된 도구 세트로 무언가를 이루려하고 있습니다. 그러나 어떤 경우에도 유형 별명을 인스턴스화 할 수있는 방법은 없습니다.

목록 만이 아니라 다른 컬렉션 유형 집합에서 기능을 작동시키려는 귀하의 목표는 무엇입니까? 이 경우 단지 공칭 디커플링 이상을 필요로합니다. 현재 함수는 여전히 List의 메소드 서명에 의존합니다.

당신은 타입 클래스를 사용하여 List의 인터페이스에서 함수를 분리 할 수 ​​있지만 MyOps에서 만들고 싶어 적이 있습니다 전화 당신은 모든 방법을 포장해야합니다 :

import scala.language.higherKinds 
import scala.reflect.ClassTag 

trait MyOps[L[_], T] { 
    def head(xs: L[T]): T 
    def tail(xs: L[T]): L[T] 
    def fromList(xs: List[T])(implicit ev: ClassTag[T]): L[T] 
} 

implicit def listMyOps[T] = new MyOps[List, T] { 
    def head(xs: List[T]) = xs.head 
    def tail(xs: List[T]) = xs.tail 
    def fromList(xs: List[T])(implicit ev: ClassTag[T]) = xs 
} 

implicit def arrayMyOps[T] = new MyOps[Array, T] { 
    def head(xs: Array[T]) = xs(0) 
    def tail(xs: Array[T]) = xs.slice(1, xs.size) 
    def fromList(xs: List[T])(implicit ev: ClassTag[T]) = xs.toArray 
} 

def foo[L[_]](xs: L[Int])(implicit ev: MyOps[L, Int]) = { 
    ev.fromList(xs = if (ev.head(xs) == -1) List(1, 2, 3) else Nil) 
} 

println(foo(List(0, 1, 2, 6))) 
println(foo(Array(-1, 6, 8))) 

출력 :

List() 
[[email protected] 

- 첫번째 foo 호출은 List를 취하고 List을 반환 둘째는 ArrayArray입니다.

+1

목표는 명확하게 추상화 및 식별입니다. MyType의 사용자는 List [Int]이고 다른 임의의 List와 MyType을 구별 할 수 있습니다. [Int] –

+0

그래서 List의 다른 유형을 위해 MyType의 백업 유형을 바꿀 수 있기를 원합니다 '? (잠깐, 네, 나는 너를 묻는 사람이라고 생각했다.) –

+0

네, 그 생각입니다. MyType을 사용하는 함수가 실제 유형에서 추상화되기를 원합니다. – cheezsteak

1

유형은 유형 일 뿐이며 인스턴스를 작성하는 방법에 대한 정보는 아닙니다.

별칭의 인스턴스를 생성하는 함수를 제공해야합니다. 에릭은 말한다 당신이 약간 뒤로 뭔가를하고있는 것처럼

그래서 예를

def foo(x: MyType)(create: List[Int] => MyType) = 
    if (x.head == 0) create(Nil) // Should Nil be used? 
    else if (x.head == -1) create(List(1,2,3,4)) 
    else x 

에 대한, 그것은 소리.

0

모든 컬렉션 유형에 대한 스칼라 컬렉션의 세계에는 컬렉션의 인스턴스를보다 쉽게 ​​구성 할 수있는 도움이되는 객체가 있습니다.당신은 단지 다음 잘못된 것 Numeric("5.1")를 작성하는 경우 클래스를 가지고 있다면

object Numeric { 
    def apply(s: String): Numeric = new Numeric(s.toDouble) 
} 

case class Numeric(v: Double) 

: 편의상

는 같은 이름의 클래스와 객체를 고려한다. 객체를 사용하면 Numeric.apply("5.1") 또는 applyspecial method이므로 실제로는 Numeric("5.1")을 쓸 수 있습니다. Scala의 object은 Java로 작성하는 모든 static 메소드를 보유하는 것과 유사합니다. 위로 예제

MyTypeList[Int]에만 유형의 별칭이며, 이름 MyType과 범위에 List 동반자 개체를 가져 오지 않습니다. 귀하의 예는 동반자 개체가없는 예인 Numeric과 같습니다.

내 대답은 1) MyType이 별칭이고 2) 컬렉션 유형이 Int으로 제한된다는 사실을 숨기는 동반자 개체를 생성하는 간단하고 일반적인 방법을 만드는 것입니다. 당신은 당신의 코드에서 이와 같은 유형의 별칭 많이 가지고 있다면 당신은 여기보다 일반적인 버전을 원하는 아마 것 :

import scala.collection.GenTraversable 
import scala.collection.generic.GenericCompanion 

class TypeCompanion[CC[X] <: GenTraversable[X], T](companion: GenericCompanion[CC]) { 
    type InnerType = CC[T] 
    def apply(elems: T*): InnerType = companion.apply(elems: _*) 
    def empty(): InnerType = companion.empty[T] 
} 

object MyType extends TypeCompanion[List, Int](List) 
type MyType = MyType.InnerType 

당신이 List 쓰기 횟수를 줄이려면, 그리고 상관하지 않습니다 당신은 몇 가지 다른 유형 Int에서 변경해야하는 경우 여분의 입력은, 당신이 변화를 선호 할 수 있습니다 :

class TypeCompanion[CC[X] <: GenTraversable[X]](companion: GenericCompanion[CC]) { 
    type InnerType = CC[Int] 
    def apply(elems: Int*): InnerType = companion.apply(elems: _*) 
    ... 
} 

object MyType extends TypeCompanion(List) 
type MyType = MyType.InnerType 

모두 구현이 foo 방법이 구현 제공 :

def foo(x: MyType): MyType = { 
    if (x.head == 0) MyType() 
    else if (x.head == -1) MyType(1,2,3,4) 
    else x 
} 

GenTraversableGenericCompanion의 형식 제한은 스칼라 컬렉션의 규칙과 일치하는 개체를 컴패니언 개체로 제한하는 데 유용합니다.

+0

나는 downvote의 목적을 이해하지 못한다 ...하지만 내 의도는 MyType의 인스턴스를 생성 할 수있게 해주는 GenericCompanion에 의해 제약되는 MyType을 정의하는 방법을 보여주기위한 것이다. – Nate

+0

나는 내 대답을 크게 단순화했다. 이 예제를 사용하면 MyType()을 사용하여 List()가 수행 할 작업을 얻을 수 있습니다. – Nate

+0

하지만이 점은 무엇입니까? 정확히 무엇을 묻는 지 묻는 답을 주시겠습니까? 그게별로 유용하지 않기 때문입니다. –

관련 문제