我是一个完整的 Haskell n00b,但我想定义一个新的数据类型,它是一个简单的数字列表。我该怎么做呢?我已经阅读了有关类型声明的 Haskell wikibook 以及其他在线资源,但我似乎无法弄清楚。本质上,这是我尝试过的:
type NumList = [Num]
那没有用,那我该怎么做呢?谢谢您的帮助。
我是一个完整的 Haskell n00b,但我想定义一个新的数据类型,它是一个简单的数字列表。我该怎么做呢?我已经阅读了有关类型声明的 Haskell wikibook 以及其他在线资源,但我似乎无法弄清楚。本质上,这是我尝试过的:
type NumList = [Num]
那没有用,那我该怎么做呢?谢谢您的帮助。
Num
是一个类,而不是一个类型。选择一种类型;例如Integer
或Rational
可能是不错的选择。
type NumList = [Integer]
但是,这不会创建新类型;它只是为旧类型创建一个新名称。如果你真的想要一个新类型,你可以使用newtype
,如
newtype NumList = MkNumList [Integer]
它定义了一个名为的新类型NumList
和一个名为 的新数据构造函数MkNumList
。
该type
关键字仅用于类型同义词(已存在的类型的新名称),因此您不能使用Num
.
相反,您可以将data
关键字与 Haskell 的上下文表示法一起使用:
data Num a => NumList a = NumList [a]
除非我在 ghci 中尝试这样做,否则它会责骂我,因为不推荐使用数据类型上下文。显然你最好使用 GADT。也许是这样的:
data NumList a where
Empty :: Num a => NumList a
Singleton :: Num a => a -> NumList a
Append :: Num a => NumList a -> NumList a -> NumList a
根据您的确切需要,有几个答案。如果您只想要特定应用程序的数字列表,您可能知道在这种情况下您将使用的确切数字类型,并且应该使用:
type DoubleList = [Double]
(我希望使用更明确的名称,因为与 [Double] 相比,DoubleList 没有任何优势)
如果您想强制使用 NumList 的每个函数都使用Num a
上下文(但它不会是自动的,这就是不推荐使用此方法的原因),您可以使用:
data Num a => NumList a = NL [a]
尽管这可能是一个坏主意,但它不会为(Num a) => ...[a]....
您在代码中的使用带来任何好处。
如果您不关心列表中数字的确切类型,只要您可以在它们之间进行操作(但不能在两个 NumList 之间),您可以使用存在类型:
data NumList = forall a . (Num a) => NL [a]
这与对象最相似,尽管使用类型擦除并且没有反射,您将无法使用 NumList 做很多事情(可以添加,但到此为止,我很确定您只是在堆积您不需要的困难只是因为你试图在 Haskell 中编写 Java/C++/Other)。
请注意,如果您想为数字列表创建 Num 实例,您可以这样做:
instance (Num a) => Num [a] where ...
我的最终建议确实是[a]
在适当的Num a
上下文中使用,但如果您认为这是错误的,如果您要获得进一步的指导,您必须提供更多关于您使用这种类型的细节。