2

Scala Id typeclass를 만들고 싶습니다. 예를 들어, Foo 타입의 Id가 Long 값을 취한다고 선언 할 수 있습니다.스칼라 컴파일러에서 다른 컴파일러 유형을 추론하려면 어떻게합니까?

val fooId: Id[Foo] = Id(12L) // type-safe at compile time 
val fooIdValue: Long = fooId.value // able to get the value back out 

다양한 방법을 시도했지만 제약 조건을 적용 할 수 없습니다. 내가

trait WithId[I] { 
    type Id = I 
} 

case class Id[A <: WithId[_]](value: A#Id) // A#Id => Any, not what I want! 

class Foo extends WithId[Long] { 
    type Id = Long 
} 

를 선언하면 내가 WithId 다음

val fooId: Id[Foo] = Id(12L) 

컴파일하지 않는 추상 형식

trait WithId { 
    type Id 
} 

case class Id[A <: WithId](value: A#Id) 

class Foo extends WithId { 
    type Id = Long 
} 

를 사용하도록 변경하면이

말,

val fooId: Id[Foo] = Id("foo") // should be illegal unless a Long 

수 있습니다

no type parameters for method apply: (value: A#Id)net.box.Id[A] in object Id exist so that it can be applied to arguments (Long) --- because --- argument expression's type is not compatible with formal parameter type; found : Long required: ?0A#Id 

Id [Foo]가 Long을 취하는 이유는 무엇입니까?

답변

3

WithId에 해당 유형 매개 변수를 제거하는 것이 옳습니다. 그러나 두 번째 문제는 어떻게 Id을 인스턴스화하는지에 따라 발생합니다. val x: Foo[T]라고 말하면, x이 원하는 타입을 지정하고 있지만, 컴파일 될 때 어떤 타입을 사용해야하는지 컴파일러를 돕는 것이 아닙니다. 컴파일러 오류로 인해 IdA에서 벗어나기를 바란다고 Foo에게 말하면서도 결과가 나옵니다. 그러나 Foo에 대해 말하지 않았습니까? A도 있습니다! 문제를 해결하려면 사용법을

val fooId = Id[Foo](12L) 
+0

으로 변경하면됩니다. 유형이있는 "전환 측"이 중요 할 것이라고 기대하지 않았습니다. 왼쪽에있는 것이 오른쪽에 삽입되면 생각할 수 있습니다. 감사! –

관련 문제