0

我创建自己的类型参数如下:

data Node a = Node a

data Cost = Int | Float

data Edge Node Cost = Edge ((Node,Node),Cost)

data Graph Edge = Graph [Edge]

并得到一个错误:

意外类型Node' where type variable expected In the declaration of的边缘节点成本'

我该如何解决?

4

1 回答 1

4

类型构造函数与数据构造函数

您必须在 haskell 中标记联合类型中的类型:

data Cost = Int | Float

应该说

data Cost = I Int | F Float

请注意,这是因为IntFloat是类型。示例数据是I 5F 5.6。我们也需要数据构造函数。I并且F是这里的数据构造函数。I :: Int -> CostF :: Float -> Cost。它们是将整数或浮点数转换为成本的函数。您可以有一个不带参数的构造函数,例如,在您的评论中,

data Bool = True | False

这里 True 和 False 是构造函数,而不是类型。示例数据只是TrueFalse。你每次都必须有构造函数,这就是为什么我们需要标记类型IntFloat

定义

data Node a = Node a

有点令人困惑,因为在左侧,Node是一种类型函数,我们称为类型构造函数,并且有 kind * -> *,但右侧Node是类型的数据构造函数a -> Node a。示例数据:Node "hello"类型Node String。如果我们写,这将不那么令人困惑

data Node a = N a

Node类型构造函数和N数据构造函数也是如此。N "Hello"这给出了类型的样本数据Node String。对于这种定义,我们并没有太大的区别,所以我们倾向于说

newtype Node a = N a

因为在大多数情况下编译器可以将其优化掉,但我们在源代码端获得了类型安全。

类型构造函数需要类型

你还需要

data Edge a = Edge ((Node a,Node a),Cost)

因为Node是一个类型构造函数(它有 kind * -> *)所以你必须总是给它一个类型来处理。我已经给了它,a所以你可以用任何东西制作你的节点。

但是,您不需要括号,并且 Int 和 Float 的联合可能不如使用小写cost而不是固定类型允许任何成本类型有用Cost

data Edge a cost = Edge (Node a) (Node a) cost

(如果你想确保没有人从任何非数字成本中获得优势,你可以说data Num cost => Edge a cost = Edge (Node a) (Node a) cost. 在我看来,这是在标记 Int 和 Float 的尴尬和允许任意成本之间更好的折衷,但是你不需要它——你可以很高兴地在你需要的时候在一个结合成本的函数上添加限制+。)

您的整个定义将是

data Node a = Node a
data Edge a cost = Edge (Node a) (Node a) cost
data Graph a c = Graph [Edge a c]

同样,您需要编写Graph [Edge a c]因为Edge需要两种类型,所以有 kind * -> * -> *

于 2012-11-22T00:45:29.920 回答