cha*_*ium 1 scala angle latitude-longitude
我有一些代码滥用Double的方式与String被滥用作为无类型类型的goto的方式大致相同.Double以这种方式使用会导致许多细微和/或隐藏的问题,通常会导致有害的运行时错误.这就是现在两种方法的样子:
object Geospatial {
def calculateDistance(
coordinate1Longitude: Double,
coordinate1Latitude: Double,
coordinate2Longitude: Double,
coordinate2Latitude: Double
): (Double, Double, Double) = {
//code encapsulated here only works with meters and radians
//returns (distance in meters, initial bearing in zero-based radians, final bearing in zero-based radians)
???
}
def calculateCoordinate(
coordinate1Longitude: Double,
coordinate1Latitude: Double,
angle: Double,
distance: Double
): (Double, Double) = {
//code encapsulated here only works with meters and radians
//returns angle in radians for longitude and latitude
???
}
}
Run Code Online (Sandbox Code Playgroud)
您可以想象,如果客户端要调用这些方法中的任何一个并且尚未正确转换为米和弧度,并且/或者忘记了方法返回以米和弧度为单位的值,则客户端将得到不正确的结果.
所以,我想显着提高上述方法的类型安全性; 即如果/当客户端试图调用这些方法中的任何一个时,我希望客户端接收编译时错误,其中传递的类型与这些方法所需的类型不完全匹配.本着这种精神,我已经重写了方法(及其上下文)以更加类型化(但仍然不够):
object Geospatial {
type AngleRadiansCentered = Double
//angle's range is restricted to [-Math.PI until Math.PI]
type AngleRadiansPositive = Double
//angle's range is restricted to [0.0d until (Math.PI * 2.0d)]
type LongitudeRadians = AngleRadiansCentered
type LatitudeRadians = AngleRadiansCentered //angle's range must be _further_ restricted to -(Math.PI / 2.0d) until (Math.PI / 2.0d)
def calculateDistance(
coordinate1: (Longitude, Latitude),
coordinate2: (Longitude, Latitude)
): (Meters, AngleRadiansPositive, AngleRadiansPositive) = {
//Legacy code encapsulated here only works with meters and radians
//returns (distance, initial bearing, final bearing)
???
}
def calculateCoordinate(
coordinate1: (Longitude, Latitude),
bearing: AngleRadiansPositive,
distance: Meters
): (Longitude, Latitude) = {
//Legacy code encapsulated here only works with meters and radians
???
}
}
Run Code Online (Sandbox Code Playgroud)
由于我一直在解决这个问题,我最近发现了猖獗的图书馆.我想我想用squants重写上面的代码.然而,花了一个小时左右阅读稀疏的squants文档(至少关于我的上下文的相关示例),我无法在如何将其应用于此问题上做出任何合理的飞跃.例如,如何指定它只接受Meters(而不是更通用的Length)方法参数.IOW,我正在寻找类型安全,而不是类型之间的转换(虽然这是我将在这些方法之外做的事情).
我找不到任何一些狡猾的示例代码snippits,我可以从中得到我需要的东西.而且我不是要求完整的解决方案.我只需指向正确的方向.首先,我需要知道squants是否真的是正确使用的API.然后,如果是的话,我需要足够的帮助来推动我朝着正确的方向发展,这样我才能找到解决方案空间的其余部分.
我打算至少使用案例类来替换所有的实例Double.在我这样做之前,我想知道是否有惯用的方法我可以用squants库做到这一点.
任何有关这方面的指导将不胜感激.
我经历了同样的过程去了,这是我发现:该squants库,至少本身,不会给你究竟你在找什么.它提供的类型安全,特指不混合不同类型的数量,但同一维度内的实际单位并不重要.
也就是说,在使用它一段时间后,我意识到它所采用的方法实际上是符合我需要的方法.您仍然可以获得重要的类型安全性:将值保持在其维度内.并且在同一维度内混合不同的单位仍然是安全的,因为您创建Length单元的方式是使用"构造函数"之一,如Meters或Centimeter.内部代表无关紧要.您正在使用Length(重要部分).如果你想原始Meter(保存到数据库?),那么请打电话toMeters.这样做不会损害类型安全.