2017-03-27 27 views
2

在Haskell中,您有產品類型,並且有元組。有關Haskell中產品類型和元組的冗餘

如果您不想將專用類型與該值關聯,則可以使用元組,如果您希望這樣做,則可以使用產品類型。

但是我覺得有冗餘產品類型的符號

data Foo = Foo (String, Int, Char) 
data Bar = Bar String Int Char 

爲何會出現這兩種符號的?有沒有什麼情況下你更喜歡另一個?

我想你在使用元組時不能使用記錄符號,但這只是一個方便的問題。另一件事可能是元組中的順序概念,而不是產品類型,但我認爲這只是由於函數fstsnd的命名。

回答

0

我不希望Foo中使用的模式頻繁。在構造函數的行爲方面略有不同:Foo :: (String, Int, Char) -> Foo而不是Bar :: String -> Int -> Char -> Bar。然後Foo undefinedFoo (undefined, ..., ...)嚴格地說是不同的事情,而你錯過Bar中的一個未定義的級別。

4

類型

data Foo = Foo (String, Int, Char) 

代表一個雙擡起元組。它的值包括

undefined 
Foo undefined 
Foo (undefined, undefined, undefined) 
etc. 

這通常很麻煩。正因爲如此,在實際代碼中很少見到這樣的定義。我們要麼有明文數據類型

data Foo = Foo String Int Char 

newtype小號

newtype Foo = Foo (String, Int, Char) 

newtype可以一樣使用不方便,但至少它 沒有做雙電梯的元組:undefinedFoo undefined是現在價值相等。

newtype還提供了在兩個方向上的普通元組和Foo之間的零成本轉換。

您可以看到使用的例如newtype,當程序員需要一個不同於一個已經與元組關聯的類的實例時。或者,也許它用於「智能構造函數」習語中。

7

@chi's answer是關於Haskell評估模型的技術差異。我希望能給你一些關於這種類型編程哲學的見解。

在分類理論中,我們通常使用「達到同構」的對象。你的Bar當然是同構於(String, Int, Char),所以從分類的角度來看它們是一回事。

bar_tuple :: Iso' Bar (String, Int, Char) 
bar_tuple = iso to from 
    where to (Bar s i c) = (s, i, c) 
      from (s, i, c) = Bar s i c 

在某種意義上元組是產品類型的柏拉圖式的形式,因爲它們沒有任何意義超越是完全不同的值的集合。所有其他產品類型可以映射到一個普通的舊元組。

那麼爲什麼不使用元組無處不在,當所有的Haskell類型的最終歸結到的乘積之和?這是關於溝通。正如Martin Fowler所說,

任何傻瓜都可以編寫計算機可以理解的代碼。好的程序員編寫人類可以理解的代碼。

名字是很重要的!寫下自定義產品類型像

data Customer = Customer { name :: String, address :: String } 

灌輸與意思閱讀代碼的人的類型Customer,不像(String, String)這只是意味着「兩個字符串」。當你想通過隱藏數據的表示和使用智能構造執行不變

自定義類型特別有用:

newtype NonEmpty a = NonEmpty [a] 

nonEmpty :: [a] -> Maybe (NonEmpty a) 
nonEmpty [] = Nothing 
nonEmpty xs = Just (NonEmpty xs) 

現在,如果你不導出NonEmpty構造,就可以迫使人們通過nonEmpty智能構造函數。如果有人給你一個NonEmpty價值,你可以安全地假設,它至少有一個元素。

當然你也可以代表Customer作爲引擎蓋下一個數組和揭露喚起名爲場存取,

newtype Customer = Bar (String, String) 
name, address :: Customer -> String 
name (Customer (n, a)) = n 
address (Customer (n, a)) = a 

,但是這並不能真正給你買得多,但它現在便宜Customer轉換爲一個元組(比如說,如果你正在寫性能敏感的代碼與面向元組的API的工作)。

如果你的代碼是爲了解決特定的問題 - 這當然是寫代碼的整點 - 它支付不只是解決問題,但使它看起來像你已經解決了這一點。有人 - 也許你在幾年 - 將不得不讀取這些代碼並沒有理解它是如何工作的先驗知識。自定義類型是這方面非常重要的溝通工具。