标签类型:类型不匹配
问题描述:
我尝试使用scalaz中的标记类型来加强类型安全性。标签类型:类型不匹配
我遇到了一个警告和一个我不明白的错误。
你能解释我两个吗?
这里是控制台输出:
scala> sealed trait PostId
defined trait PostId
scala> def PostId(l: Long) : Long @@ PostId = Tag[Long, PostId](l)
PostId: (l: Long)[email protected]@[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 : [email protected]@[Long,PostId]
(which expands to) Long with AnyRef{type Tag = PostId}
required: PostId
Post(PostId(2l))
答
在你的榜样,PostId
只是一个标签类型。 实际的tagg-ed类型(您应该操纵的类型)是Long @@ PostId
。
错误在于,如果您确实需要使用Long @@ PostId
的实例(因此类型不匹配),则您已定义Post
以获取PostId
的实例。
我建议重命名PostId
到PostIdTag
和定义PostId
作为别名Long @@ PostId
:
sealed trait PostIdTag
type PostId = Long @@ PostIdTag
def PostId(l: Long) : PostId = Tag[Long, PostIdTag](l)
然后你就可以保持你的Post
定义为。
UPDATE:事实证明,scalaz标签类型似乎只与类型<工作:AnyRef
,即一个不能创建从AnyVal
子类型标记类型。
然后将溶液是更换Long
与java.lang.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))
我的不好,应该是'Long @@ PostIdTag',而不是'Long @@ PostId'。我更新了我的答案。 –
一个新的错误:scala> case class Post(id:PostId) error:type mismatch; 找到的:任何 必需:AnyRef 注意:任何不会隐式转换为AnyRef。您可以安全地使用 模式匹配'x:AnyRef'或强制执行'x.asInstanceOf [AnyRef]'来执行此操作。 –