Haskell 如何使用类型来分隔不兼容的值

Haskell 如何使用类型来分隔不兼容的值,haskell,Haskell,我正在写一个大地测量计算库。我想包括的一件事是网格投影的类型(例如,军械测量国家网格)和这些网格上的点(由“东向”和“北向”指定)。栅格由一个将其连接到地球的原点和一组几何参数指定。应用程序程序员可以使用这些参数创建许多任意网格。根据不同的基础投影,还将有一系列类型的网格 显然,我希望能够对网格点进行计算(例如距离、方位等), 但同时我想使用Haskell类型的系统来防止应用程序程序员询问不同网格上两点之间的距离。我想知道一个读卡器Monad是否可以按照ST Monad的方式使用类型参数,但是我

我正在写一个大地测量计算库。我想包括的一件事是网格投影的类型(例如,军械测量国家网格)和这些网格上的点(由“东向”和“北向”指定)。栅格由一个将其连接到地球的原点和一组几何参数指定。应用程序程序员可以使用这些参数创建许多任意网格。根据不同的基础投影,还将有一系列类型的网格

显然,我希望能够对网格点进行计算(例如距离、方位等),
但同时我想使用Haskell类型的系统来防止应用程序程序员询问不同网格上两点之间的距离。我想知道一个读卡器Monad是否可以按照ST Monad的方式使用类型参数,但是我希望应用程序程序员能够在Monad之外存储这些位置值,而ST则是为了防止STRefs从runST泄漏

我也有一个类似的问题,在下面的椭球体上的大地坐标位置(纬度和经度)。但是网格版本可能更容易解释,因为这个问题的焦点是类型系统而不是大地测量学


我读过GADT和存在主义类型,但我不知道如何做到这一点

您可以使用两个GHC扩展来标记坐标,坐标来自网格:

{-# LANGUAGE DataKinds, KindSignatures #-}

data CoordinateType = Geodetic | OSNG -- etc.

data Coordinate (grid :: CoordinateType) = Coord Int Int

zeroZero :: Coordinate Geodetic
zeroZero = Coord 0 0
(扩展在GHC 7.4+中工作,不确定是否有更低的版本。)

然后,任何需要它的函数都可以强制执行
网格
幻影参数的相等性:

distance :: Coordinate grid -> Coordinate grid -> Float
distance p q = undefined

现在
distance zeroZero(Coord 1 2::Coord OSNG)
给出了一个类型错误。

可能是一种使用类型算术的方法:“但同时我想使用Haskell类型系统来防止应用程序程序员询问不同网格上两点之间的距离”——为什么?点可能定义在不同的网格上,但仍然表示相同的物理位置,为什么不允许计算这些点之间的距离?@leftaroundabout:是的,但这需要坐标变换和更复杂的计算。此外,在某些情况下,简单的平面计算是正确的(例如,在处理雷达时)。我认为安全和自动地进行这种“复杂计算”(它们不会那么难,是吗?只有容易出错,如果不是自动处理的话)当然应该由您的库负责,事实上,我认为这是图书馆的主要目的之一。但是,大地测量学并不是我的专业,它更多的是管理精度和参考系的问题。除非你正在处理一个巨大的重力局部变化校正表,否则不能依靠坐标转换来保持精度。看看Wikipedia关于Geoid的文章,如果我理解正确的话,它只适用于硬编码的CoordinationType值列表(实际上我已经使用类型类完成了这项工作,尽管更详细)。我想说“data CoordType=Grid Double Double”,这样“foo=Grid 3 4;bar=Grid 2 4.2”就可以在类型级别区分“foo”中的坐标和“bar”中的坐标。@PaulJohnson,您不局限于硬编码的值列表,因为(现在需要GHC 7.6)您可以在类型级别(“提升的文字”)使用字符串和自然值。关于data->kind升级的文档是,你可以看看其中是否有帮助。但它们也必须是文字:我不能(据我所知)从文件中读取字符串并将其升级为类型。甚至不需要任何datakind内容;一个简单的phantom类型参数也可以做到这一点,并且与较旧的ghc版本兼容。