2016-10-02 53 views
2

我都像預計下列工作:無形:UnaryTCConstraint 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 。類型,FooWithAnyDependency]。

我知道實現一個自定義約束將解決問題(我已經完成了),但是當我嘗試使用別的東西時遇到同樣的問題,例如:Comapped.Aux[L, FooWithAnyDependency, M]

所以問題是,我如何克服這個問題,而不必爲Foo重新實現大多數事情。

回答

2

你完全正確的問題是推斷HNil.type單身類型。與無形的工作時

case class Foo[R, L <: HList](
    result: R, 
    dependencies: L = HNil: HNil 
)(implicit utcc: UnaryTCConstraint[L, FooWithAnyDependency]) 

一般來說,你需要爲HNil提供類型註釋這樣避免了(或多或少沒用:幸運的是,解決方法是非常簡單的,你只需要提供一個類型標註爲HNil )單式HNil.type,當你寫這樣的事情,除了:

val hlist = 1 :: HNil 

這將對推斷出的類型Int :: HNil而不是Int :: HNil.type只是因爲HNil::方法,確保ŧ你會得到正確的類型。

+0

這個工作'val aFoo = Foo(「abc」)'但這個'val bFoo = Foo(5,aFoo :: HNil)'不。錯誤是:'無法找到參數utcc的隱式值:shapeless.UnaryTCConstraint [shapeless。:: [Foo [String,HNil],HNil],FooWithAnyDependency]'。我不明白爲什麼。 –

+1

@SimãoMartins看起來像一個統一問題。我建議編寫自己的類型類來捕獲約束。 –

相關問題