0

下面的haskell代码编译好了,好的。

data Point = Point Float Float  
data Radius = Radius Float  
data Shape = Circle Point Radius

是否可以按照下面的代码编写一些东西(代码编译失败):

data LengthQty = Radius Float | Length Float | Width Float   
data Shape = Circle Point Radius

这一尝试背后的想法是半径、长度和宽度代表物理量长度。

请注意,在第二部分的第二行中,如果这样写

data Shape = Circle Point LengthQty

然后,它会编译,但在这种情况下,“LengthQty”可以是长度、宽度或半径之类的任何东西,其中只需要半径。

(1) 第二部分有什么问题?
(2)如何纠正实现物理量长度(LengthQty)的思想?

4

3 回答 3

2

您的代码无法编译的原因是数据声明的右侧必须是一个构造函数,后跟一个类型列表,即形式

data {-type-} = {-constructor-} {-type-} ... {-type-}

在您的示例中,当您定义

data LengthQty = Radius Float | Length Float | Width Float 

你已经创建了一个LengthQty类型whileRadius是构造函数。因此,当你写LengthWidth

data Shape = Circle Point Radius

编译器看到一些形式

data {-type-} = {-constructor-} {-type-} {-constructor-}

即它看到一个构造函数,它期望一个类型,所以它抛出一个错误。在原始代码中,该符号Radius同时用于构造函数和类型。当编译器看到

data Shape = Circle Point Radius

它知道Radius在这种情况下必须是一个类型,因此不可能与构造函数半径混淆。

考虑到这一点,如果您只编写代码,就可以使您的代码正确编译

data Shape = Circle Point LengthQty

你可以得到一个圆的特定实例

circle :: Shape
circle = Circle (Point 0 0) (Radius 1)
于 2012-07-19T18:20:35.283 回答
2

这编译:

data Point = Point Float Float  
data Radius = Radius Float  
data Shape = Circle Point Radius

data LengthQty = R Float | Length Float | Width Float   

Radius是类型的名称,也是类型的数据构造函数的名称Float -> RadiusR是类型的数据构造函数Float -> LengthQty。您不能有两个具有相同名称的不同数据构造函数。这个名字 Radius已经被占用了

以下也有效:

data LengthQty = R Radius | Length Float | Width Float 

如果没有RRadius其本身将是一个类型的数据构造函数:: LengthQty,这将再次与 . 冲突Radius :: Float -> Radius

于 2012-07-19T18:29:36.463 回答
0

有用的区别

data Point = Point Float Float  
data Radius = Radius Float  
data Shape = Circle Point Radius


data LengthQty = Radius Float | Length Float | Width Float

是 Haskell 的类型系统处理它们的方式。Haskell 有一个强大的类型系统,它可以确保向函数传递它可以处理的数据。您编写类似定义的原因LengthQuantity是,如果您有一个可以采用 a RadiusLengthWidth的函数,而您的函数无法做到这一点。

如果您确实有一个可以采用 , 或 的函数RadiusLengthWidth会这样编写您的类型:

data Point = Point Float Float  
data Radius = Radius Float  
data Shape = Circle Point Radius

data LengthQty = R Radius
               | L Length 
               | W Width

这样,只能Radius从更具体的类型检查中受益的函数。

于 2012-07-19T19:44:56.770 回答