简体   繁体   English

scalaz 中定义的 @@ 运算符是什么?

[英]What is this @@ operator defined in scalaz?

When browsing a piece of Scala code at aws-scala by Atlassian you can find the following line:Atlassian 的 aws-scala 上浏览一段 Scala 代码时,您可以找到以下行:

type QueueURL = String @@ QueueURL.Marker

I am new to Scala, so I might be wrong, but the @@ (double at-sign) doesn't seem like a standard built-in Scala operator.我是 Scala 的新手,所以我可能是错的,但@@ (双 at 符号)似乎不是标准的内置 Scala 运算符。 Moreover, an observant reader will find it imported from 'scalaz' library:此外,细心的读者会发现它是从 'scalaz' 库中导入的:

import scalaz.{ Tag, @@ }

What does the @@ do? @@什么作用? And why is it used?为什么使用它?

As mentioned in the comments, the actual definition is :正如评论中提到的, 实际定义是

 type @@[A, T] = A

which might be some hint.这可能是一些提示。

The idea of tag is that quite often you don't want to use raw Long s, Int s and so on everywhere - well, you want to use them in your code, but you don't want to pass them on interface level: tag 的想法是,你通常不想在任何地方使用原始Long s、 Int s 等等——好吧,你想在你的代码中使用它们,但你不想在接口级别传递它们:

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

here you have to used named parameters in order to make sure that you didn't swap the order of arguments.在这里你必须使用命名参数以确保你没有交换参数的顺序。 Additionally someone might make the mistake of overriding it with wrong order:此外,有人可能会错误地以错误的顺序覆盖它:

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

To avoid that you can use different types for both arguments.为避免这种情况,您可以对两个参数使用不同的类型。 One way yo do it is to use case class with AnyVal - if you follow few rules it is optimized by compiler to primitives.一种方法是使用带有AnyVal案例类 - 如果您遵循一些规则,它会被编译器优化为原语。 Tags are alternative method to introduce new types for some common types (that might not necessarily be primitives).标签是为一些常见类型(可能不一定是原语)引入新类型的替代方法。 @@ is defined as @@定义为

type @@[A, T] = A

as you noticed.正如你所注意到的。 So you could define new type as:因此,您可以将新类型定义为:

@@[String, QueueURL.Marker]

but because Scala allow us to use infix syntax on types, we can write it also as:但是因为 Scala 允许我们在类型上使用中缀语法,我们也可以将它写成:

String @@ QueueURL.Marker

It is especially useful if you make dependency injection with eg implicits or Macwire - there arguments are fetch based only on types, and so having distinguished type for each injectable value is a must (on a side-note Macwire implements it's own version of @@ - they did it slightly different way, but it serves the same purpose).如果您使用例如implicits 或Macwire 进行依赖注入,则它特别有用 - 参数仅基于类型获取,因此必须为每个可注入值指定不同的类型(旁注 Macwire 实现了它自己的@@版本) - 他们的做法略有不同,但目的相同)。

Then you can end up with a code like this:然后你可以得到这样的代码:

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

or:或者:

type UsersNumber = Int @@ UsersNumberTag
type UsersOffset = Int @@ UsersOffsetTag

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

I also saw this variant:我也看到了这个变种:

type UsersNumber[T] = T @@ UsersNumberTag
type UsersOffset[T] = T @@ UsersOffsetTag

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

Looking at the aws-scala code I assume they wanted to achieve the first property - being able to distinguish different usages of some common types (like String ) and use compiler to check if they didn't make a mistake.查看 aws-scala 代码,我假设他们想要实现第一个属性 - 能够区分一些常见类型(如String )的不同用法,并使用编译器来检查他们是否没有犯错。

Example in ammonite:以菊石为例:

@ type @@[A, T] = A with T
defined type @@

@ trait Username
defined trait Username

@ def passUsername(username: String @@ Username): Unit = ()
defined function passUsername

@ passUsername("test")
cmd3.sc:1: type mismatch;
  String|String with Username
val res3 = passUsername("test")
                        ^
Compilation Failed

Tagging makes creating new types easy.标记使创建新类型变得容易。 It uses the @@ symbol to "tag" an existing type as another type (in other words, it creates a new type).它使用@@ 符号将现有类型“标记”为另一种类型(换句话说,它创建了一个新类型)。 So String @@ Text should be read as "String tagged with Text".所以 String @@ Text 应该读作“String tagged with Text”。 Not sure why it is used.不知道为什么使用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM