![](/img/trans.png)
[英]Scala 'type mismatch error' while using a function but works fine for method
[英]Scala type mismatch while trying to pass a function
我需要一些幫助,試圖弄清楚如何重用我不想重復的模式匹配(如果可能)。 我在這里和Google進行過搜索,嘗試了隱式和方差,但到目前為止沒有任何結果。
在下面是兩種方法,doSomething和doSomethingElse在id上包含相同的模式匹配。 我想通過傳入一個函數來重用該模式。
這是初始設置。 (toPath和take2的實際實現並不真正相關。)
import java.nio.file.{Paths, Path}
import java.util.UUID
def take2(x: Long): String = {
(x % 100).toString.padTo(2, '0')
}
def take2(u: UUID): String = {
u.toString.take(2)
}
def toPath(x: Long): Path = {
Paths.get(s"$x")
}
def toPath(u: UUID): Path = {
Paths.get(u.toString)
}
case class Ids(id1: Option[Long], id2: Option[UUID])
def doSomething(ids: Ids): String = ids match {
case Ids(_, Some(uuid)) => take2(uuid)
case Ids(Some(long), _) => take2(long)
}
def doSomethingElse(ids: Ids) = ids match {
case Ids(_, Some(uuid)) => toPath(uuid)
case Ids(Some(long), _) => toPath(long)
}
doSomething(Ids(Some(12345L), None))
doSomethingElse(Ids(Some(12345L), None))
我想要的是這樣的事情:
def execute[A](ids: Ids)(f: Any => A): A = ids match {
case Ids(_, Some(uuid)) => f(uuid)
case Ids(Some(long), _) => f(long)
}
def _doSomething(ids: Ids) = execute[String](ids)(take2)
//def _doSomething2(ids: Ids) = execute[Path](ids)(toPath)
我得到的錯誤是:
Error: ... type mismatch;
found : (u: java.util.UUID)String <and> (x: Long)String
required: Any => String
def _doSomething(ids: Ids) = execute[String](ids)(take2)
^ ^
請問如何使這些功能類型起作用?
我的Scala版本2.11.2。
我一直在使用的工作表: https : //github.com/lhohan/scala-pg/blob/0f1416a6c1d3e26d248c0ef2de404bab76ac4e57/src/main/scala/misc/MethodPassing.sc
任何幫助或指針,感激不盡。
問題是您有兩種不同的方法碰巧共享相同的名稱,例如“ take2”。 當您嘗試使用take2
您肯定沒有提供可以處理任何參數類型的函數(如Any => A
要求的)。 您甚至無法處理所需的兩種類型,因為它們是兩種不同的方法!
在原始的match語句中,您不會注意到這兩個方法是兩個共享相同名稱的方法,因為編譯器會根據參數類型填寫正確的方法。 沒有一個功能可以說:“插入我提供的名稱,然后使用其他方法”。 (嗯,您可以使用宏來做到這一點,但是要避免重復一點就太復雜了。)
現在,編譯器是足夠聰明,做一個函數出你想要的方法。 所以如果你寫
def execute[A](ids: Ids)(f1: UUID => A, f2: Long => A): A = ids match {
case Ids(_, Some(uuid)) => f1(uuid)
case Ids(Some(long), _) => f2(long)
}
然后你可以
def doSomething(ids: Ids) = execute[String](ids)(take2, take2)
這會減少重復。
或者,您可以編寫
import scala.util._
def take2(x: Long): String = (x % 100).toString.padTo(2, '0')
def take2(u: UUID): String = u.toString.take(2)
def take2(ul: Either[UUID, Long]): String = ul match {
case Left(u) => take2(u)
case Right(l) => take2(l)
}
(如果在REPL中嘗試使用:paste
,請確保使用:paste
,以便將所有三個一起定義)。
然后你寫
def execute[A](ids: Ids)(f: Either[UUID, Long] => A): A = ids match {
case Ids(_, Some(uuid)) => f(Left(uuid))
case Ids(Some(long), _) => f(Right(long))
}
並且將使用三個take2
的正確之一。 (與參數的額外裝箱相關的運行時懲罰,但是我懷疑這是對性能至關重要的代碼路徑。)
還有其他選項-例如Shapeless提供聯合類型。 或者,如果您傳遞的內容既不是UUID
也不是Long
,則可以執行運行時模式匹配並拋出異常,但是以后可能會引起麻煩。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.