說我有與狀態的狀態單子爲HList
和我定義了一個組合子負責這種HList
的第一n
元素:查找類型的類實例
import scalaz._, Scalaz._
import shapeless._, ops.hlist._, Nat._
def take[S <: HList](n: Nat)(implicit tk: Take[S, n.N]):
IndexedState[S, tk.Out, Unit] = ???
for {
_ <- init[Int :: String :: HNil]
_ <- take(_1)
x <- state("abc")
} yield x
的在類型推斷期間scala編譯器被卡住了。它並不推斷take
的S
類型參數是Int :: String :: HNil
。因此,編譯器無法找到參數tk
的隱含值。
[error] could not find implicit value for parameter tk: shapeless.ops.hlist.Take[S,shapeless.Nat._1.N]
[error] _ <- take(_1)
我知道,我可以通過簡單地暴露狀態或者通過固定S
幫助編譯器。但我不想!這種額外的信息似乎是多餘的:
def take[S <: HList](hl: S, n: Nat)(implicit tk: Take[S, n.N]):
IndexedState[S, tk.Out, Unit] = ???
for {
hl <- init[Int :: String :: HNil]
_ <- take(hl, _1) // Redundant
_ <- take[Int :: HNil](_1) // Redundant
x <- state("abc")
} yield x
爲什麼在第一個代碼段,Scala編譯器推斷S
作爲Nothing
而不是Int :: String :: HNil
?我想知道是否可以在不暴露狀態或提供類型信息的情況下獲得此作品?
在此先感謝!
我不認爲編譯器有足夠的信息來推斷'S' - 它所知道的'S'就是在範圍內必須有一個'Take [S,nN]'實例,並且存在一個寬各種不同的'S'。你和我知道期望的返回類型是'IndexedReaderWriterStateT [...,S,...]',但是從那裏到相當複雜的路徑,意識到'S'必須是'take'的類型參數。當您將預期類型展開爲例如'採取(_1):IndexedReaderWriterStateT [...]',這是否得到正確推斷? – lmm 2015-02-23 17:13:10
@Imm - 你確定編譯器沒有足夠的信息來推斷'S'嗎? 'init [Int :: String :: HNil]'給出了一個'IndexedState [Int :: String :: HNil,Int :: String :: HNil,Int :: String :: HNil]'。如果我們遵循這些類型,那麼'flatMap'應該構造一個構造'IndexedState [Int :: String :: HNil,?,?]'的函數。我們給出返回一個IndexedState [S,tk.Out,Unit]的'{_ => take(_1)}'。我認爲兩者之間的匹配應該將'S'修復爲'Int :: String :: HNil'。我在這裏錯過了什麼? – 2015-02-24 12:52:08