我刚刚开始学习Haskell,但仍然没有掌握函数式编程。我需要创建一个多态数据类型,直到我编写的函数之一运行之前,我才知道其类型。该程序似乎要我从列表中构建元组列表,例如:
['Car', 'Car', 'Motorcycle', 'Motorcycle', 'Motorcycle', 'Truck']
将转换为[('Car', 2), ('Motorcycle', 3), ('Truck', 1)]
。
在相同的元组列表(一个包)中,所有元素都属于同一类型,但是不同的包中可能包含其他类型。现在,我的数据类型声明(我不确定在FP中是否称为“声明”)
type Amount = Int
data Bag a = [(a, Amount)]
但是,当我尝试加载模块时,出现此错误:
Cannot parse data constructor in a data/newtype declaration: [(a, Amount)]
如果在声明中将data
更改为type
,则会收到所有功能的错误消息:
Expecting one more argument to ‘Bag’
Expected a type, but ‘Bag’ has kind ‘* -> *’
关于FP,我是否不了解某些事情?还是代码错误?更重要的是,如何以一种实际上允许我将模块加载到GHCi中的方式声明这一点?
答案 0 :(得分:8)
data
类型这与函数式编程本身无关。如果您定义data
类型(或newtype
),则在Haskell中它需要一个数据构造函数(对于newtype
,只能有一个 数据构造函数,并带有一个参数)。对于数据构造函数,[(a, Amount)]
并不是一个好“名字”(无论如何,您都不打算将其用作数据构造函数)。
我们在这里可以编写一个数据构造函数,例如:
data Bag a = Bag [(a, Amount)]
,由于这里Bag
包含(可能)一个带有 one 参数的数据构造函数,因此我们可以将其设为newtype
:
newtype Bag a = Bag [(a, Amount)]
但是,上面的内容可能不是必需的:您可能想用type
声明 alias 类型:
type Bag a = [(a, Amount)]
在那种情况下,您没有构造新的类型,但是您可以编写Bag a
,并且在“幕后”,Haskell将其替换为[(a, Amount)]
。
Bag
定义功能如果您现在想定义一个处理Bag
的函数,则还需要在签名中指定参数a
,例如:
count :: Eq a => [a] -> Bag a
count = -- ...
现在很明显,我们在a
个Bag
中转换了a
个列表。