本文介绍了标记类型:类型不匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试使用 scalaz 的 Tagged Type 来加强类型安全.

I try to use Tagged Type from scalaz to strengthen type safety.

我遇到了一个我不明白的警告和错误.

I encountered a warning and an error that I don't understand.

你能解释一下吗?

这是控制台的输出:

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))

推荐答案

在您的示例中,PostId 只是一种标记类型.实际的标记ed 类型(您应该操作的类型)是Long @@ PostId.

In your example, PostId is just a tag type.The actual tagg-ed type (the type that you should manipulate) is Long @@ PostId.

错误是您定义了 Post 以获取 PostId 的实例,而您确实想让它获取 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.

我建议将 PostId 重命名为 PostIdTag 并将 PostId 定义为 Long @@ PostId 的别名:

I suggest renaming PostId to PostIdTag and defining PostId as an alias to Long @@ PostId:

sealed trait PostIdTag
type PostId = Long @@ PostIdTag

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

然后你可以保持你的 Post 定义不变.

Then you can keep your Post definition as is.

UPDATE:事实证明,scalaz 标记类型似乎只适用于 AnyRef 类型,即不能从 创建标记类型AnyVal 子类型.

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.

解决方案是将 Long 替换为 java.lang.Long(这是透明的,因为 Scala 会自动转换 java.lang.Long> 值到 Long):

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):

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))

这篇关于标记类型:类型不匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

06-23 11:07