2017-11-17 7 views
1

のは、私は次のコードがあるとしましょう:Scalaの暗黙および型の別名

object Potato extends App { 

    type CoolString = String 
    type AwesomeString = String 

    def potato(string: String)(implicit coolString: CoolString, awesomeString: AwesomeString) = { 
    s"$string is a string. Oh, but don't forget - $coolString and also $awesomeString" 
    } 

    implicit val ice : CoolString = "Really Cold Ice" 
    implicit val awe : AwesomeString = "Awe inspiring object" 

    potato("Stringerino") 

} 

このコードは問題

[error] ... ambiguous implicit values: 
[error] both value ice in object Potato of type => Potato.CoolString 
[error] and value awe in object Potato of type => Potato.AwesomeString 
[error] match expected type Potato.CoolString 
[error] potato("Stringerino") 

で失敗することは不可能暗黙のような使用ですか?

答えて

4

このような暗黙の使用は不可能ですか?

暗黙のうちにStringという一般的な形式を取るこのような方法に頼るのは危険です。それについて考えると、スコープ内のStringインスタンスは、メソッドに渡される適格な候補になります!

タイプエイリアスはちょうど、タイプエイリアスです。コンパイラにCoolStringAwesomeStringの両方が単にStringです。

より良いアプローチは、タグ付きタイプを活用することです。たとえば、これはtagged type using shapelessです:

import [email protected]@ 

trait CoolString 
trait AwesomeString 

type ReallyCoolString = String @@ CoolString 
type ReallyAwesomeString = String @@ AwesomeString 

そして:

import shapeless.tag 

def potato(string: String)(implicit coolString: ReallyCoolString, awesomeString: ReallyAwesomeString) = { 
    s"$string is a string. Oh, but don't forget - $coolString and also $awesomeString" 
} 

def main(args: Array[String]): Unit = { 
    implicit val ice = tag[CoolString][String]("Really Cold Ice") 
    implicit val awe = tag[AwesomeString][String]("Awe inspiring object") 

    println(potato("Stringerino")) 
} 

収量:

Stringerino is a string. 
Oh, but don't forget - Really Cold Ice and also Awe inspiring object 
関連する問題