2012-07-19 62 views
0

下面的haskell代碼編譯好了。haskell - LYAH - 製作我們自己的類型和我們的類型

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)如何修正以實現物理數量長度(長度Qty)的概念?

+1

這是國際海事組織不是在LYAH最好的例子之一,'數據半徑=半徑浮點數'實際上是一個相當愚蠢的定義,你通常只會寫'類型半徑=浮點數'這種東西。並使用記錄systax來進一步闡明'Circle'中每個字段的含義。 – leftaroundabout 2012-07-20 07:15:20

回答

2

的原因,您的代碼不會編譯是一個數據聲明的右邊必須是一個構造其次類型,即形式

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

的列表在您的例子,當你定義

data LengthQty = Radius Float | Length Float | Width Float 

所做LengthQty一個Radius,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) 
+0

在Haskell中,Type Classes可以有Sub Type Classes嗎? – Optimight 2012-07-19 18:53:05

+1

類型類可以有子類,但「子類」這個詞的含義與它在OO語言中的含義不同。 – 2012-07-19 19:10:37

+0

@優化不是真的。您可以爲實例執行上下文需求,但是...但是,上下文需求在解析過程之後進行檢查,而不是在解析過程中使用。 – alternative 2012-07-20 00:24:03

2

這編譯:

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

data LengthQty = R Float | Length Float | Width Float 

Radius是類型的名稱,也是類型的數據構造函數的名稱; RFloat -> LengthQty類型的數據構造函數。您不能有兩個具有相同名稱的不同數據構造函數。 名稱Radius已經採取

下也可以工作:

data LengthQty = R Radius | Length Float | Width Float 

沒有RRadius本身是:: LengthQty類型的數據構造,這將再次對陣Radius :: Float -> Radius

+0

類型類在haskell中可以有子類型嗎? – Optimight 2012-07-19 18:53:11

+2

你在這裏沒有使用任何類。您正在使用數據類型。但Haskell中的類(與面向對象的類完全不同)確實可以有子類。 – dflemstr 2012-07-19 18:55:41

+0

dflemstr:是的,我讀過它,但在評論中提出我的問題時完全錯過了它。仍然面向對象的範式思維覆蓋。我的問題應該是:「數據類型有沒有可能在haskell中有子數據類型? – Optimight 2012-07-20 00:34:20

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這樣的定義的原因是,如果你有一個功能可以接受你的功能無法做到的Radius,LengthWidth

如果沒有有可能採取RadiusLength,或者Width,我會寫你的類型這樣的功能:

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

data LengthQty = R Radius 
       | L Length 
       | W Width 

這種方式,功能,只能採取Radius好處從更具體的類型檢查。

相關問題