标签类型:类型不匹配(Tagged type : type mismatch)

2019-10-19 05:55发布

我尝试用标记类型从scalaz加强型安全。

我遇到了一个警告,并且我不明白的错误。

你能解释一下我两者兼而有之?

这里是控制台输出:

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

Answer 1:

在你的榜样, PostId仅仅是一个标签类型。 实际tagg- 型(你应该操纵型)是Long @@ PostId

该错误是你定义Post采取的一个实例PostId ,当你真正的意思有它采取的一个实例Long @@ PostId ,因此类型不匹配。

我建议重命名PostIdPostIdTag和定义PostId作为别名Long @@ PostId

sealed trait PostIdTag
type PostId = Long @@ PostIdTag

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

然后,你可以让你的Post定义为是。

更新 :事实证明,scalaz标签类型似乎只与类型<工作: AnyRef ,即,一个不能创建从一个标记的类型AnyVal子类型。

那么解决的办法是,以取代Long使用java.lang.Long (其中透明地工作,因为Scala将自动转换java.lang.LongLong ):

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


文章来源: Tagged type : type mismatch
标签: scala scalaz