2016-11-02 13 views
2

私はDebasish Ghoshの新刊「Functional and Reactive Domain Modeling」を読んでいます。本当に楽しんでいます。ここでは、Seq上でどのようなScala暗黙の変換が行われていますか?

Reporting.report(accts).foreach(println _) 

のSeq [アカウント]を取るとのSeq [表示]に変換することができます:私は困惑している第5章で

ことの一つは、以下の行がどのようです。私は暗黙のうちにあることを知っているが、これをコンパイルするためにはどのようなステップが必要か?これはより一般的な暗黙のルールの特定のインスタンスですか? のように見えますが、コンパイラはShowの特性をAccountオブジェクトに混ぜています。ありがとう!

ページから適応

164:

import scala.util.Try 

trait Show[T] { 
    def shows(t: T): Try[String] 
} 

trait ShowProtocol { 
    implicit val showAccount: Show[Account] 
    implicit val showCustomer: Show[Customer] 
} 

trait DomainShowProtocol extends ShowProtocol { 
    override implicit val showAccount: Show[Account] = (t: Account) => Try("Account") 
    override implicit val showCustomer: Show[Customer] = (t: Customer) => Try("Customer") 
} 

case class Account() 
case class Customer() 

object Reporting { 
    def report[T: Show](as: Seq[T]): Seq[Try[String]] = as.map(implicitly[Show[T]].shows _) 
} 

object DomainShowProtocol extends DomainShowProtocol 

object Main { 
    def main(args: Array[String]): Unit = { 
    import DomainShowProtocol._ 

    val accts: Seq[Account] = Seq(
     Account(), 
     Account(), 
     Account() 
    ) 

    Reporting.report(accts).foreach(println _) 
    } 
} 

答えて

1

シンタックスシュガー

def report[T: Show](seq: Seq[T]) 

大体あなたは

012を想定することができ

def report(seq: Seq[T])(implicit evidence: Show[T]) 

ためのシンタックスシュガーであります

(implicit evidence: Show[T]) 

implicitly[Show[T]] 

の仕事が特色DomainShowProtocol今すぐオブジェクトDomainShowProtocolを使用してShow[Account]

object DomainShowProtocol extends DomainShowProtocol 

暗黙の証拠を持っている暗黙のショーの参照は何も[T]

ではないん暗黙的にスコープにインポートされます。

report方法がので順番に機能上に形質DomainShowProtocol

def report[T: Show](as: Seq[T]): Seq[Try[String]] = as.map(implicitly[Show[T]].shows _) 

から来ているオブジェクトDomainShowProtocolからimplicit証拠Seq[Try[String]]Seq[Account]を変換することができる

def report(as: Seq[T])(implicit evidence: Show[T]): Seq[Try[String]] = as.map(evidence.shows _) 

ための糖衣構文でありますここでTAccountであり、暗黙の証拠Show[Account]はcommオブジェクトDomainShowProtocolから送信します。この変換がどのように可能か

+0

感謝。彼らは本当に私が文法的な甘えを味わうのを助けてくれました。あなたが証言した注釈は全く新しいものでしたので、 "Aha!"瞬間! –

3

これはかなり単純なtypeclassパターンの使用です。すべての「魔法」はreport機能で起こります。

最初の通知タイプパラメータ:

def report[T: Show] 

これはどんなタイプTは呼び出しサイトで範囲内の暗黙のShow[T]がなければならない、であることを意味します。 Mainでは、関数はTAccountであるため呼び出されます。したがって暗黙のShow[Account]がその行のスコープ内にあることが必要です。MainDomainShowProtocolに混在しているため、暗黙的な値showAccountは範囲内にあるため、その要件は満たされています。

reportの本文には、implicitly[Show[T]]が使用されています。これは、スコープ内にあることが要求された非常にShow[T]への参照を返します。したがって、この場合はshowAccountに等しくなります。

最後に、showメソッドが暗黙的に返された値に対して呼び出され、Seqの現在の要素をパラメータとして渡します。これにより、AccountはそれぞれTry[String]に変換され、全体としてSeqに変換されます。

我々はすべての暗黙のマジックを削除する場合は、メソッドとその呼び出しは次のようになります。あなたの編集のための

//in Reporting 
def report[T](as: Seq[T])(show: Show[T]): Seq[Try[String]] = { 
    as.map{t => show.shows(t)} 
} 

//in Main 
Reporting.report(accts)(accountsShow).foreach(println _) 
+0

ステップごとに説明してくれてありがとう! –

関連する問題