[英]What's the recommended way of handling complexly composed POD(plain-old-data in OO) in Haskell?
我是 Haskell 新手。
在靜態類型的面向對象語言(例如 Java)中,所有復雜的數據結構都以類和實例的形式呈現。 一個對象可以有許多屬性(字段)。 而另一個對象可以是該字段的值。 可以使用它們的名稱訪問這些字段,並按類靜態鍵入。 最后,這些對象構建了相互鏈接的巨大對象圖。 大多數程序使用這樣的數據圖。
如何在 Haskell 中歸檔這些功能?
如果你確實有沒有行為的數據,這很好地映射到 Haskell 記錄:
data Person = Person { name :: String
, address :: String }
deriving (Eq, Read, Show)
data Department = Management | Accounting | IT | Programming
deriving (Eq, Read, Show)
data Employee = Employee { identity :: Person
, idNumber :: Int
, department :: Department }
| Contractor { identity :: Person
, company :: String }
deriving (Eq, Read, Show)
這表示Person
是具有name
和address
(均為String
)的Person
; 一個Department
是Management
、 Accounting
、 IT
或Programming
; 和Employee
或者是一個Employee
誰擁有的identity
(一個Person
),一個idNumber
(的Int
)和department
(一Department
),或者是一個Contractor
誰擁有的identity
(一個Person
)與company
(一個String
) . deriving (Eq, Read, Show)
行使您能夠比較這些對象的相等性、讀入它們並將它們轉換為字符串。
通常,Haskell 數據類型是聯合(也稱為sums )和元組(也稱為products )的組合。 1 |
s 表示選擇(一個聯合):一個Employee
要么是一個Employee
要么是一個Contractor
,一個Department
是四個事物之一,等等。 一般來說,元組的寫法如下:
data Process = Process String Int
這表示Process
(除了作為類型名稱)是一個類型為String -> Int -> Process
的數據構造函數。 因此,例如, Process "init" 1
或Process "ls" 57300
。 Process
必須同時具有String
和Int
才能存在。 上面使用的記錄符號只是這些產品的語法糖; 我也可以寫data Person = Person String String
,然后定義
name :: Person -> String
name (Person n _) = n
address :: Person -> String
address (Person _ a) = a
然而,記錄表示法對於復雜的數據結構可能很好。
另請注意,您可以將 Haskell 類型參數化為其他類型; 例如,一個三維點可以是data Point3 a = Point3 aaa
。 這意味着Point3 :: a -> a -> a -> Point3 a
,這樣就可以寫Point3 (3 :: Int) (4 :: Int) (5 :: Int)
來獲得Point3 Int
或Point3 (1.1 :: Double) (2.2 :: Double) (3.3 :: Double)
得到Point3 Double
。 (或者Point3 1 2 3
得到一個Num a => Point3 a
,如果你見過類型類和重載的數字文字。)
這是表示數據圖所需要的。 然而,請注意:對於從命令式語言過渡到函數式語言——或者,實際上,在任何兩種不同的范式(C 到 Python,Prolog 到 Ruby,Erlang 到 Java,等等)之間——的一個問題是繼續嘗試解決問題舊的方式。 您嘗試建模的解決方案可能無法以適合簡單的函數式編程技術的方式構建,即使問題是。 例如,在 Haskell 中,考慮類型非常重要,其方式與 Java 不同。 同時,為這些類型實現行為的方式非常不同:高階函數捕獲了您在 Java 中看到的一些抽象,但也捕獲了一些不容易表達的抽象( map :: (a -> b) -> [a] -> [b]
, filter :: (a -> Bool) -> [a] -> [a]
和foldr :: (a -> b -> b) -> b -> [a] -> b
想到)。 因此,請保持您的選擇余地,並考慮以實用的方式解決您的問題。 當然,在這種情況下,您可能會全力以赴。 但是在探索一門新語言時請記住這一點。 玩得開心:-)
1:和遞歸:可以表示一個二叉樹,比如用data Tree a = Leaf a | Branch a (Tree a) (Tree a)
data Tree a = Leaf a | Branch a (Tree a) (Tree a)
。
Haskell 有代數數據類型,它可以描述結構或結構的聯合,這樣給定類型的東西可以包含許多不同的字段集之一。 這些字段可以按位置或通過具有記錄語法的名稱來設置和訪問。
見這里: http : //learnyouahaskell.com/making-our-own-types-and-typeclasses
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.