简体   繁体   English

标记类型:类型不匹配

[英]Tagged type : type mismatch

I try to use Tagged Type from scalaz to strengthen type safety. 我尝试使用scalaz中的Tagged Type来加强类型安全性。

I encountered a warning and an error that I don't understand. 我遇到了一个我不明白的警告和错误。

Can you explain me both ? 你能解释我两个吗?

Here is the output of the console : 这是控制台的输出:

scala> sealed trait PostId
defined trait PostId

scala> def PostId(l: Long) : Long @@ PostId = Tag[Long, PostId](l)
PostId: (l: Long)scalaz.@@[Long,PostId]
warning: previously defined trait PostId is not a companion to method PostId.
Companions must be defined together; you may wish to use :paste mode for this.

scala> case class Post(id: PostId)
defined class Post

scala> Post(PostId(2l))
<console>:26: error: type mismatch;
 found   : scalaz.@@[Long,PostId]
    (which expands to)  Long with AnyRef{type Tag = PostId}
 required: PostId
              Post(PostId(2l))

In your example, PostId is just a tag type. 在您的示例中, PostId只是一种标记类型。 The actual tagg- ed type (the type that you should manipulate) is Long @@ PostId . 实际tagg- 型(你应该操纵型)是Long @@ PostId

The error is that you have defined Post to take an instance of PostId when you really meant to have it take an instance of Long @@ PostId , hence the type mismatch. 错误是你已经定义了Post来获取PostId的实例,当你真的想让它采用Long @@ PostId的实例时,因此类型不匹配。

I suggest renaming PostId to PostIdTag and defining PostId as an alias to Long @@ PostId : 我建议重命名PostIdPostIdTag和定义PostId作为别名Long @@ PostId

sealed trait PostIdTag
type PostId = Long @@ PostIdTag

def PostId(l: Long) : PostId = Tag[Long, PostIdTag](l)

Then you can keep your Post definition as is. 然后你可以保持你的Post定义。

UPDATE : As it turns out, scalaz tagged types seem to only work with types <: AnyRef , ie one cannot create a tagged type from an AnyVal sub-type. 更新 :事实证明,scalaz标记类型似乎只适用于类型<: AnyRef ,即无法从AnyVal子类型创建标记类型。

The solution then is to replace Long with java.lang.Long (which works transparently because scala will automatically convert java.lang.Long values to Long ): 然后解决方案是用java.lang.Long替换Long (它透明地工作,因为scala会自动将java.lang.Long值转换为Long ):

sealed trait PostIdTag
type PostId = java.lang.Long @@ PostIdTag
def PostId(l: java.lang.Long) : PostId = Tag[java.lang.Long, PostIdTag](l)
case class Post(id: PostId)
Post(PostId(2l))

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

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