在Scala中,是否可以使用类型,但不允许使用像Haskell这样的别名/
发布时间:2020-12-16 09:21:06 所属栏目:安全 来源:网络整理
导读:在Haskell中,我相信可以以类似于别名的方式使编译器不允许别名类型和未混叠类型之间的引用.根据 this stack overflow question,可以使用Haskell的新类型: newtype Feet = Feet Doublenewtype Cm = Cm Double 其中脚和Cm将表现为Double值,但尝试乘以一个脚值
在Haskell中,我相信可以以类似于别名的方式使编译器不允许别名类型和未混叠类型之间的引用.根据
this stack overflow question,可以使用Haskell的新类型:
newtype Feet = Feet Double newtype Cm = Cm Double 其中脚和Cm将表现为Double值,但尝试乘以一个脚值和Cm值将导致编译器错误. 编辑:Ben在评论中指出,上述Haskell的定义不足.脚和Cm将是新的类型,将不会定义函数.做更多的研究,我发现以下内容将会起作用: newtype Feet = Feet Double deriving (Num) newtype Cm = Cm Double deriving (Num) 这将创建一个从现有的Num类型派生的新类型(需要使用switch:-XGeneralizedNewtypeDeriving).当然,这些新类型将从其他类型(如Show,Eq等)中获得更多的价值,但这是正确评估Cm 7 * Cm 9所需的最小值. Haskell和Scala都有类型,它简单地使现有的类型别名,并允许无意义的代码,如Scala中的这个例子: type Feet = Double type Cm = Double val widthInFeet: Feet = 1.0 val widthInCm: Cm = 30.48 val nonsense = widthInFeet * widthInCm def getWidthInFeet: Feet = widthInCm Scala是否具有新的等价物,假设这样做是我认为的? 解决方法
是的,你在scala中使用了被称为“无框标签类型”的东西.
这是Tagged的定义: type Tagged[U] = { type Tag = U } type @@[T,U] = T with Tagged[U] 这可以让你做这样的事情 sealed trait Feet def Feet[A](a: A): A @@ Feet = Tag[A,Feet](a) Feet: [A](a: A)scalaz.@@[A,Feet] scala> val mass = Feet(20.0) mass: scalaz.@@[Double,Feet] = 20.0 scala> 2 * mass res2: Double = 40.0 也添加CM sealed trait CM def CM[A](a: A): A @@ CM = Tag[A,CM](a) CM: [A](a: A)scalaz.@@[A,CM] scala> val mass = CM(20.0) mass: scalaz.@@[Double,CM] = 20.0 如果要将乘法限制为仅限于脚,则可以编写类型类型乘法函数 trait Multiply[T] { self => def multiply(a: T,b: T): T } implicit val footInstance = new Multiply[Feet] { def multiply(a: Feet,b: Feet): Feet = Feet(a * b) } implicit val cmInstance = new Multiply[CM] { def multiply(a: CM,b: CM): CM = CM(a * b) } def multiply[T: Multiply](a: T,b: T): T = { val multi = implicitly[Multiply[T]] multi.multiply(a,b) } 你可以这样做 multiply(Feet(5),Feet(10)) // would return Feet(50) 这是最好的Scala可以做的 要了解有关盒装类型的更多信息,请查看 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |