类型参数错误

时间:2012-11-22 00:43:30

标签: haskell

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

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边缘节点成本'

我该如何解决?

1 个答案:

答案 0 :(得分:4)

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

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

data Cost = Int | Float

应该说

data Cost = I Int | F Float

请注意,这是因为IntFloat是类型。示例数据为I 5F 5.6。我们也需要数据构造函数。 IF是数据构造函数。 I :: Int -> CostF :: Float -> Cost。它们是将Ints或Floats转化为成本的功能。你可以有一个不带参数的构造函数,例如,在评论中,

data Bool = True | False

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

的原因

定义

data Node a = Node a

有点令人困惑,因为在左侧,Node是一种类型函数,我们称之为类型构造函数,并且具有类* -> *,但在右侧{{1}是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)所以你必须总是给它一个类型来处理。我已经给它* -> *所以你可以让你的节点摆脱任何东西。

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

Cost

(如果你想确保没有一个人能从任何非数字成本中获得优势,你可以说data Edge a cost = Edge (Node a) (Node a) cost 。在我看来,在标记Int的尴尬之间有一个更好的折衷方案。并且浮动并允许任意成本,但是你不需要它 - 你可以非常高兴地在一个将成本与data Num cost => Edge a cost = Edge (Node a) (Node a) cost结合起来的函数上准确地添加限制。)

您的整个定义将是

+

同样,您需要撰写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种类。