首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >scalaz中定义的@@运算符是什么?

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

Stack Overflow用户
提问于 2017-02-22 23:58:22
回答 2查看 1.8K关注 0票数 5

浏览piece of Scala code at aws-scala by Atlassian时,您可以找到以下行:

代码语言:javascript
复制
type QueueURL = String @@ QueueURL.Marker

我是Scala的新手,所以我可能错了,但是@@ (double at-sign)看起来不像是标准的内置Scala运算符。此外,细心的读者会发现它是从“scalaz”库中导入的:

代码语言:javascript
复制
import scalaz.{ Tag, @@ }

@@是做什么的?为什么要用它呢?

正如评论中所提到的,actual definition is

代码语言:javascript
复制
 type @@[A, T] = A

这可能是一些提示。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-02-23 18:52:29

tag的想法是,通常你不想在任何地方使用原始的LongInt等等--你想在代码中使用它们,但又不想在接口层传递它们:

代码语言:javascript
复制
def fetchUsers(numberOfUsers: Int, offset: Int): Seq[User]

在这里,您必须使用命名参数,以确保您没有交换参数的顺序。另外,有些人可能会犯这样的错误,用错误的顺序覆盖它:

代码语言:javascript
复制
override def fetchUsers(offset: Int, numberOfUsers: Int): Seq[User]

为了避免这种情况,您可以对两个参数使用不同的类型。一种方法是使用带有AnyVal的case类-如果你遵循一些规则,它会被编译器优化为原语。标记是为一些常见类型(可能不一定是基元类型)引入新类型的替代方法。@@被定义为

代码语言:javascript
复制
type @@[A, T] = A

如你所见。因此,您可以将新类型定义为:

代码语言:javascript
复制
@@[String, QueueURL.Marker]

但是因为Scala允许我们在类型上使用infix语法,所以我们也可以这样写:

代码语言:javascript
复制
String @@ QueueURL.Marker

如果你使用implicits或Macwire进行依赖注入,那么它特别有用--它们的参数只是基于类型来获取的,所以每个可注入的值都必须有不同的类型(顺便说一句,Macwire实现了它自己版本的@@ --它们的方式略有不同,但服务于相同的目的)。

然后,您可以使用如下代码结束:

代码语言:javascript
复制
def fetchUsers(numberOfUsers: Int @@ UsersNumber, offset: Int @@ Offset): Seq[User]

或者:

代码语言:javascript
复制
type UsersNumber = Int @@ UsersNumberTag
type UsersOffset = Int @@ UsersOffsetTag

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

我还看到了这个变体:

代码语言:javascript
复制
type UsersNumber[T] = T @@ UsersNumberTag
type UsersOffset[T] = T @@ UsersOffsetTag

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

看一下aws-scala代码,我假设他们想要实现第一个属性-能够区分一些常见类型(如String)的不同用法,并使用编译器检查他们是否犯了错误。

菊石中的示例:

代码语言:javascript
复制
@ 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
票数 9
EN

Stack Overflow用户

发布于 2017-02-22 23:59:53

标记使得创建新类型变得很容易。它使用@@符号将现有类型“标记”为另一个类型(换句话说,它创建了一个新类型)。因此,String @@ Text应该读作“带有文本标记的字符串”。不确定为什么要使用它。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42396382

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档