我创建自己的类型参数如下:
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
的边缘节点成本'
我该如何解决?
我创建自己的类型参数如下:
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
的边缘节点成本'
我该如何解决?
您必须在 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
。它们是将整数或浮点数转换为成本的函数。您可以有一个不带参数的构造函数,例如,在您的评论中,
data Bool = True | False
这里 True 和 False 是构造函数,而不是类型。示例数据只是True
或False
。你每次都必须有构造函数,这就是为什么我们需要标记类型Int
和Float
定义
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 * -> * -> *
。