我创建自己的类型参数如下:
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
边缘节点成本'
我该如何解决?
答案 0 :(得分:4)
您必须在haskell中标记联合类型中的类型:
data Cost = Int | Float
应该说
data Cost = I Int | F Float
请注意,这是因为Int
和Float
是类型。示例数据为I 5
或F 5.6
。我们也需要数据构造函数。 I
和F
是数据构造函数。 I :: Int -> Cost
和F :: Float -> Cost
。它们是将Ints或Floats转化为成本的功能。你可以有一个不带参数的构造函数,例如,在评论中,
data Bool = True | False
这里的True和False是构造函数,而不是类型。示例数据仅为True
或False
。您每次都必须拥有构造函数,这就是我们需要标记类型Int
和Float
定义
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
种类。