저는 유형을 사용하여 엔티티 단위를 확인하는 경제적 모델을위한 작은 라이브러리에서 작업하고 있습니다. val apples = 2.0
대신 val apples = GoodsAmount[KG, Apples](2.0)
이라고 적어주세요. 상품 묶음을 만들기 위해 무형의 라이브러리에서 HLists를 사용하려고했습니다. 이 잘 작동하지만 어떤 경우에는 내가 선호하는 일반 코드로 수 없습니다. 예 : 다음 문제.무형의 : 다형 함수의 유형 제약 검사
나는 엉망이 될 수있는 것을 설명하는 간단한 코드로 시작합니다. 우리는 Km을 나타내는 두 클래스와 다른 마일을 만듭니다. Km 클래스는 추가 할 수 있지만 마일은 추가 할 수 없습니다. 추상적 인 유형 T를 사용한다는 것은 주로 더 복잡한 라이브러리가되도록 동기 부여됩니다. 그리고 '+'함수에 대한 간접 호출은 무형의 경우에서 비슷한 것을 필요로하기 때문입니다.
trait Foo {
type T
val v: Double
def +[B <: Foo](other: B)(implicit ev: this.T =:= other.T) = v + other.v
}
trait _Km
trait _Miles
case class Km(v: Double) extends Foo { type T = _Km }
case class Miles(v: Double) extends Foo { type T = _Miles }
object ExampleSimple extends App {
def add[A <: Foo, B <: Foo](a: A, b: B)(implicit ev: a.T =:= b.T) = { a + b }
add(Km(1), Km(2))
// add(Km(1), Miles(2)) /* does not compile as intended */
}
이것은 의도 한대로 작동합니다. 그러나 'Add'기능에 대한 Type Contraint 검사가 필요합니다. 경우, 첫 번째 오류를 수정해야
[error] /home/fuerst/gitg3m/code/types/src/main/scala/lagom_d/extract.scala:50: Cannot prove that a.T =:= b.T.
[error] implicit def caseTuple[A <: Foo] = at[(A,A)] { case (a: Foo, b) => a + b }
[error] ^
[error] /home/fuerst/gitg3m/code/types/src/main/scala/lagom_d/extract.scala:54: could not find implicit value for parameter mapper: shapeless.Mapper[ExampleShapeless.add.type,shapeless.::[(Km, Km),shapeless.::[(Km, Km),shapeless.HNil]]]
[error] (l1 zip l2).map(add)
: HLists이를 확장하는 나의 시도는 다음과 같습니다
object ExampleShapeless extends App {
import shapeless._
val l1 = Km(1) :: Km(2) :: HNil
val l2 = Km(4) :: Km(3) :: HNil
object add extends Poly1 {
implicit def caseTuple[A <: Foo] = at[(A,A)] { case (a, b) => a + b }
}
(l1 zip l2).map(add)
}
를하지만이 (스칼라 2.10.2을 사용하여) 다음과 같은 오류 메시지를 생성 caseTuple 함수에 유형 제약 조건을 추가 할 수는 있지만 솔직히 말해서 at 함수가 작동하는 방식과 암시 적 증거 매개 변수를 추가 할 수있는 위치를 이해하지 못했습니다. 또한 저는 매퍼가 암묵적인 가치를 발견 할 수 있도록하기 위해 무엇을해야하는지 모릅니다. 내가
implicit def caseTuple = at[(Km,Km)] { case (a, b) => a + b }
으로 caseTuple 기능을 replase
덜 일반 버전은 잘 작동하지만 현재의 솔루션을 사용하는 것과 중복 코드를 많이 (좋아,이 솔루션은 여전히 더 나은 것를 작성해야 튜플). 누군가이 문제를 해결할 수있는 힌트를 어떻게 줄 수 있습니까?
감사합니다, KLINKE
당신은 경우에 유형 매개 변수를 추가하여 일치하는 유형의 구성원을 필요로 할 수
다음과 같이'Foo'를 정의 할 수 있습니다 :'trait Foo [T <: Foo] {v : Double; + (t T) : T = ...}'. '클래스 Km (val v : Double)은 Foo [Km]'을 확장합니다. 'implicit def add [T] = at [(Foo [T], Foo [T])] – senia