我有以下工作:
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]
。< / p>
所以问题是,如何在不必为Foo重新实现大多数事情的情况下克服这个问题。
答案 0 :(得分:2)
问题是推断的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
有一个::
方法可确保您获得正确的类型。