我在Haskell中写了一个数学Vector
模块。
所以我开始时:
data Vector a = Vector !a !a !a deriving (Eq, Show)
很好 - 这让我可以使用我想要的任何数值数据类型。问题在于我不想在任何地方写Double
和Vector Double
,原因很简单,我不应该这样做。所以我补充说:
type Scalar = Double
type Vector = Vector Scalar
但当然第二行是错误的,因为现在有两个Vector
的声明。那么我该怎么改呢?我想,不,我将在我的代码中编写这个,所以我想将类型别名简单地保留为Vector
。这意味着我必须更改数据类型名称。但是,如果我改变了,那么我觉得我也应该改变构造函数,这会使一切更加混乱。但是如果感觉很尴尬,那么构造函数就会以这种方式与类型别名相同。
现在我有这个:
type Scalar = Double
type Vector = VectorT Scalar
data VectorT a = Vector !a !a !a deriving (Eq, Show)
我随意选择了T
(我猜它代表“类型”),但我对此并不十分肯定。通常,当我记录函数时,我会说-- Calculate the magnitude of a Vector
,但是VectorT
我觉得我应该真的使用那个类型名称。所以我只是将它们称为vectors
(不是大写) - 除了我觉得我必须将此约定应用于每种数据类型的每个注释。
有没有人遇到类似的情况?在这种情况下,有人会想到更优雅的解决方案吗?
答案 0 :(得分:8)
您的特定问题的一个解决方案是将数据类型放在与同义词类型不同的模块中。也就是说,有一个Math.Vector
模块,它包含数据声明和一些通用函数(即适用于所有数字类型的函数)。然后,当您在代码中实际使用Vector Double
时,只需使用限定导入创建类型同义词:
import qualified Math.Vector as MV
type Scalar = Double
type Vector = MV.Vector Scalar
我认为从代码组织的角度来看,这是有道理的。特别是,如果您已定义Vector
类型以处理所有数字类型,我希望该模块中的函数也适用于所有数字类型。您在代码的其他部分中大量使用Vector Double
这一事实不应影响实际定义Vector
的模块。毕竟,想象在你的程序的另一部分中使用Vector Int
是完全合理的。
顺便说一句,我不确定是否称呼Vector
是最好的主意。向量不一定必须有三个维度,因此我将您的数据类型称为Vector3D
。这实际上是一些其他API(如Java 3D API)中使用的名称,因此它可能是一个不错的选择。
答案 1 :(得分:2)
是否有任何具体原因不能做到
data Vector = Vector !Double !Double !Double deriving (Eq, Show)
这对我来说似乎是最简单的想法......