2017-02-22 47 views
0

當瀏覽一個piece of Scala code at aws-scala by Atlassian你可以找到以下行:在scalaz中定義的這個@@操作符是什麼?

type QueueURL = String @@ QueueURL.Marker 

我是新來的Scala,所以我可能是錯的,但@@(雙at符號)似乎並不像一個標準的內置在Scala運算符中。而且,細心的讀者會發現它從「scalaz」庫中導入:

import scalaz.{ Tag, @@ } 

什麼是@@嗎?爲什麼它被使用?

正如在評論中提到的,actual definition is

type @@[A, T] = A 

這可能是一些提示。

+0

'https:// github.com/scalaz/scalaz'似乎沒有提及它。 –

+1

它定義在[這裏](https://github.com/scalaz/scalaz/blob/series/7.3.x/core/src/main/scala/scalaz/Tag.scala#L99)。 –

回答

2

標籤的想法很多時候你不想使用原始的Long s,Int s等等 - 無論如何,你想在代碼中使用它們,但你不想傳遞它們在接口級別上:

def fetchUsers(numberOfUsers: Int, offset: Int): Seq[User] 

在這裏你必須使用命名參數,以確保你沒有交換參數的順序。另外有人可能會作出與錯誤的順序覆蓋它的錯誤:

override def fetchUsers(offset: Int, numberOfUsers: Int): Seq[User] 

要避免這種情況,你可以使用不同類型的兩個參數。其中一種方法是使用AnyVal的案例類 - 如果遵循一些規則,它會被編譯器優化爲原語。標籤是爲一些常見類型(可能不一定是原語)引入新類型的替代方法。 @@定義爲

type @@[A, T] = A 

正如您注意到的那樣。所以,你可以定義新的類型:

@@[String, QueueURL.Marker] 

但因爲Scala允許我們使用的類型綴語法,我們也可以把它寫成:

String @@ QueueURL.Marker 

,如果你做的依賴注入是非常有用的與例如implicits或Macwire - 這些參數僅基於類型獲取,因此必須爲每個注入值設置不同的類型(注意Macwire實現了它自己的版本@@--它們做的稍微有點不同,但它服務於相同的目的)。

看着aws-scala代碼,我假設他們想要實現第一個屬性 - 能夠區分某些常見類型的不同用法(如String)並使用編譯器檢查它們是否沒有出錯。

0

標記使創建新類型變得簡單。它使用@@符號將現有類型「標記」爲另一種類型(換句話說,它創建了一個新類型)。所以字符串@@文本應該被讀作「用文本標記字符串」。不知道爲什麼它被使用。

+0

'tagging'是什麼意思?像包裝一樣 - 與'Option'類似?(從類型的角度來看) –

+0

@GrzegorzOledzki標記意味着賦予某種類型特殊的含義。 – ZhekaKozlov

相關問題