我是一个完整的Haskell n00b,但我想定义一个简单的数字列表的新数据类型。我该怎么做呢?我已经在类型声明以及其他在线资源上阅读了Haskell wikibook,但我似乎无法弄明白。从本质上讲,这是我尝试过的:
type NumList = [Num]
那不行,所以我怎么能这样做?谢谢你的帮助。
答案 0 :(得分:6)
Num
是一个类,而不是一个类。选择一种类型;例如Integer
或Rational
可能是不错的选择。
type NumList = [Integer]
但是,不创建新类型;它只是为旧类型创建一个新名称。如果您确实需要新类型,则可以使用newtype
,如
newtype NumList = MkNumList [Integer]
定义了一个名为NumList
的新类型和一个名为MkNumList
的新数据构造函数。
答案 1 :(得分:2)
type
关键字仅适用于类型同义词(已存在类型的新名称),因此您无法使用Num
之类的类。
相反,您可以将data
关键字与Haskell的上下文表示法一起使用:
data Num a => NumList a = NumList [a]
除非我在ghci中尝试,否则它会责骂我datatype contexts are deprecated。显然你最好使用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
答案 2 :(得分:1)
根据您的确切需要,有几个答案。如果您只想要特定应用程序的编号列表,您可能知道在这种情况下您将使用的确切类型的数字,并且应该使用:
type DoubleList = [Double]
(更明确的名称,我希望DoubleList与[Double]相比没有任何优势)
如果要强制使用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
上下文,但如果您认为错误,则必须提供有关此类型使用的更多详细信息获得进一步的指导。