Shapeless:Foo[T, U] 的 UnaryTCConstraint
Shapeless: UnaryTCConstraint for Foo[T, U]
我有以下工作按预期进行:
import shapeless._
import shapeless.UnaryTCConstraint._
import shapeless.test.illTyped
case class Foo[R](result: R, dependencies: Set[Foo[_]] = Set.empty)
//This method only accepts an HList of Foo
def method[L <: HList](list: L)(implicit utcc: UnaryTCConstraint[L, Foo]) = println("checks")
val notFoos = "abc" :: 1 :: 5.5 :: HNil
illTyped { """method(notFoos)""" }
val aFoo = Foo("abc")
val bFoo = Foo(2, Set(aFoo))
val cFoo = Foo(true, Set(bFoo))
val onlyFoos = aFoo :: bFoo :: cFoo :: HNil
method(onlyFoos) // prints checks
经过一些重构后,我得出的结论是依赖项应该是 Foos 的 HList。所以我将代码更改为:
type FooWithAnyDependency[R] = Foo[R, _ <: HList]
case class Foo[R, L <: HList](result: R, dependencies: L = HNil)(implicit utcc: UnaryTCConstraint[L, FooWithAnyDependency])
def method2[L <: HList](list: L)(implicit utcc: UnaryTCConstraint[L, FooWithAnyDependency]) = println("checks")
这段代码可以编译,但是当我尝试使用它时:
val aFoo = Foo("abc")
我收到这个错误:
Could not find implicit value for parameter utcc: shapeless.UnaryTCConstraint[shapeless.HNil.type,FooWithAnyDependency]
Error occurred in an application involving default arguments.
val aFoo = Foo("abc")
^
我认为它失败是因为它试图找到一个 UnaryTCConstraint[HNil .type, FooWithAnyDependency.
我知道实现自定义约束可以解决问题(我已经做到了),但是每当我尝试使用其他东西时,我 运行 都会遇到同样的问题,例如:Comapped.Aux[L, FooWithAnyDependency, M]
.
所以问题是,我怎样才能克服这个问题,而不必为 Foo 重新实现大多数东西。
您完全正确,问题是推断的 HNil.type
单例类型。幸运的是,修复非常简单——您只需为 HNil
:
提供类型注释
case class Foo[R, L <: HList](
result: R,
dependencies: L = HNil: HNil
)(implicit utcc: UnaryTCConstraint[L, FooWithAnyDependency])
通常,在使用 Shapeless 时,您需要为 HNil
提供这样的类型注释,以避免(或多或少无用的)单例类型 HNil.type
,除非您写一些东西像这样:
val hlist = 1 :: HNil
它将具有推断类型 Int :: HNil
而不是 Int :: HNil.type
只是因为 HNil
有一个 ::
方法可以确保您获得正确的类型。
我有以下工作按预期进行:
import shapeless._
import shapeless.UnaryTCConstraint._
import shapeless.test.illTyped
case class Foo[R](result: R, dependencies: Set[Foo[_]] = Set.empty)
//This method only accepts an HList of Foo
def method[L <: HList](list: L)(implicit utcc: UnaryTCConstraint[L, Foo]) = println("checks")
val notFoos = "abc" :: 1 :: 5.5 :: HNil
illTyped { """method(notFoos)""" }
val aFoo = Foo("abc")
val bFoo = Foo(2, Set(aFoo))
val cFoo = Foo(true, Set(bFoo))
val onlyFoos = aFoo :: bFoo :: cFoo :: HNil
method(onlyFoos) // prints checks
经过一些重构后,我得出的结论是依赖项应该是 Foos 的 HList。所以我将代码更改为:
type FooWithAnyDependency[R] = Foo[R, _ <: HList]
case class Foo[R, L <: HList](result: R, dependencies: L = HNil)(implicit utcc: UnaryTCConstraint[L, FooWithAnyDependency])
def method2[L <: HList](list: L)(implicit utcc: UnaryTCConstraint[L, FooWithAnyDependency]) = println("checks")
这段代码可以编译,但是当我尝试使用它时:
val aFoo = Foo("abc")
我收到这个错误:
Could not find implicit value for parameter utcc: shapeless.UnaryTCConstraint[shapeless.HNil.type,FooWithAnyDependency]
Error occurred in an application involving default arguments.
val aFoo = Foo("abc")
^
我认为它失败是因为它试图找到一个 UnaryTCConstraint[HNil .type, FooWithAnyDependency.
我知道实现自定义约束可以解决问题(我已经做到了),但是每当我尝试使用其他东西时,我 运行 都会遇到同样的问题,例如:Comapped.Aux[L, FooWithAnyDependency, M]
.
所以问题是,我怎样才能克服这个问题,而不必为 Foo 重新实现大多数东西。
您完全正确,问题是推断的 HNil.type
单例类型。幸运的是,修复非常简单——您只需为 HNil
:
case class Foo[R, L <: HList](
result: R,
dependencies: L = HNil: HNil
)(implicit utcc: UnaryTCConstraint[L, FooWithAnyDependency])
通常,在使用 Shapeless 时,您需要为 HNil
提供这样的类型注释,以避免(或多或少无用的)单例类型 HNil.type
,除非您写一些东西像这样:
val hlist = 1 :: HNil
它将具有推断类型 Int :: HNil
而不是 Int :: HNil.type
只是因为 HNil
有一个 ::
方法可以确保您获得正确的类型。