簡體   English   中英

Haskell使用數據類型

[英]Haskell usage of data type

我正在閱讀制作我們自己的類型和類型類來學習你的哈克爾。

代數數據類型介紹中我注意到:

data Point = Point Float Float deriving (Show)  
data Shape = Circle Point Float | Rectangle Point Point deriving (Show)

surface :: Shape -> Float
surface (Rectangle (Point x1 y1) (Point x2 y2)) = abs (x2 - x1) * abs (y2 - y1) 

surface (Rectangle (Point x1 y1) (Point x2 y2)) ,我們指出Rectangle的參數是Point類型。

但是,在遞歸數據結構部分中:

data Tree a = EmptyTree | Node a (Tree a) (Tree a) deriving (Show, Read, Eq)
singleton :: a -> Tree a  
singleton x = Node x EmptyTree EmptyTree  

treeInsert :: (Ord a) => a -> Tree a -> Tree a  
treeInsert x EmptyTree = singleton x  
treeInsert x (Node a left right)   
    | x == a = Node x left right  
    | x < a  = Node a (treeInsert x left) right  
    | x > a  = Node a left (treeInsert x right)

我們沒有指出leftright的數據類型是treeInsert x (Node a left right)中的Tree a treeInsert x (Node a left right) 編譯器如何知道它們的類型?

我覺得你有一個誤解:

surface (Rectangle (Point x1 y1) (Point x2 y2)) ,我們指出Rectangle的參數是Point類型。

這確實表明參數屬於point類型,但可能與您的想法不同。 Point x1 y1的“ Point ”不是一個類型 - 它是一個構造函數,其命名方式與它構造的類型相同。 如果我們宣布Point

data Point = MakePoint Float Float

然后你會說

surface (Rectangle (MakePoint x1 y1) (MakePoint x2 y2)) 

為清楚起見,我將繼續使用MakePoint作為構造函數,使用Point作為類型。 合法的Haskell將其命名為相同,因為編譯器總是可以從上下文中判斷,但人類有時會遇到更多麻煩。

在上下文中

surface (Rectangle (MakePoint x1 y1) (MakePoint x2 y2)) = ...

我們知道子表達式MakePoint x1 y1具有來自兩個不同位置的Point類型。 一個是構造函數Rectangle具有類型

Rectangle :: Point -> Point -> Shape

所以我們知道,無論它的參數必須是點(這是由外向內的類型推斷,我們得到的來自其中它的使用范圍內的事情型); 另一個是構造函數MakePoint有類型

MakePoint :: Float -> Float -> Point

所以我們知道MakePoint x1 y1表示Point類型的值(這是由里而外的類型推斷,我們從其組件中獲取表達式的類型)。 在某種程度上,編譯器使用這兩種方法並確保它們匹配。

但是,有時缺少這些信息中的一種或另一種,例如我們的例子中的x1 我們沒有關於x1內部信息(好吧,如果我們查看方程式的右側,編譯器也MakePoint ,但我們現在忽略它),我們所擁有的只是MakePoint的參數構造函數必須是Float ,所以我們知道x1必須是Float 這是編譯器有效和推斷的; 沒有必要明確說明。

Tree例子中,更令人困惑的命名正在進行(一旦你得到它,不再混淆並開始有用,但最好在開始時畫出明顯的區別),所以我要重命名第一個Nodeav

treeInsert :: (Ord a) => a -> Tree a -> Tree a  
treeInsert x EmptyTree = singleton x  
treeInsert x (Node v left right)   
    | x == v = Node x left right  
    | x < v  = Node v (treeInsert x left) right  
    | x > v  = Node v left (treeInsert x right)

同樣的事情與發生leftright這一點與x1上面:沒有由內而外的結構使用,但我們知道, Node構造函數采用a和兩個Tree a S,所以v的類型必須a ,和leftright 必須Tree a類型。 編譯器從上下文中推斷出這一點。

在surface (Rectangle (Point x1 y1) (Point x2 y2)) ,我們指出Rectangle的參數是Point類型。

不,這是你的錯誤觀念。 由於數據聲明,編譯器知道Rectangle參數的類型:

data ... | Rectangle Point Point

在您引用的代碼中:

surface (Rectangle (Point x1 y1) (Point x2 y2))

這稱為模式匹配。 Surface采用矩形,我們將模式匹配,以便將變量名稱綁定到參數。 我們還對每個參數進行模式匹配以獲得對子參數的訪問並綁定變量名稱x1y1x2y2

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM