回答
type
聲明類型同義詞。類型同義詞是現有類型的新名稱。例如,這是多麼String
定義in the standard library:
type String = [Char]
String
是爲Char
的List的另一個名稱。 GHC將在編譯時用[Char]
替換程序中的所有用法String
。
要清楚,String
字面上是列表Char
s。這只是一個別名。您可以使用String
值的所有標準列表功能:
-- length :: [a] -> Int
ghci> length "haskell"
7
-- reverse :: [a] -> [a]
ghci> reverse "functional"
"lanoitcnuf"
data
聲明一個新的數據類型,它不像一個類型的同義詞,是不同於其他任何類型的不同。數據類型有多個構造函數定義您的類型的可能情況。例如,這是多麼Bool
定義in the standard library:
data Bool = False | True
甲Bool
值可以是True
或False
。數據類型支持模式匹配,允許您對數據類型的值執行運行時案例分析。
yesno :: Bool -> String
yesno True = "yes"
yesno False = "no"
data
類型可以有多個構造(與Bool
),可以由其它類型的進行參數設置,可以包含在其內部其他類型,並且可以遞歸指自己。這裏有一個例外的模型來證明這一點。一個Error a
包含類型爲a
的錯誤消息,並可能導致錯誤消息。
data Error a = Error { value :: a, cause :: Maybe Error }
type ErrorWithMessage = Error String
myError1, myError2 :: ErrorWithMessage
myError1 = Error "woops" Nothing
myError2 = Error "myError1 was thrown" (Just myError1)
重要的是要認識到,data
聲明瞭一個新類型,是除了系統中的任何其它類型很重要。如果String
已被聲明爲data
類型包含列表Char
(而不是類型同義詞),您將無法使用任何列表功能。
data String = MkString [Char]
myString = MkString ['h', 'e', 'l', 'l', 'o']
myReversedString = reverse myString -- type error
還有一個更有多種類型聲明:newtype
。這很像一個data
聲明 - 它引入了一種獨立於任何其他類型的新數據類型,並且可以進行模式匹配 - 除了您僅限於具有單個字段的單個構造函數。換句話說,newtype
是一個data
類型,它包裝了一個現有的類型。
重要的區別在於成本newtype
:編譯器承諾newtype
以與其包裝類型相同的方式表示。打包或解包newtype
沒有運行時間成本。這使得newtype
可用於制定管理(而不是結構)值之間的區別。
newtype
s與類型類很好地交互。例如,考慮Monoid
,這是一種將元素(mappend
)和特殊「空」元素(mempty
)組合在一起的類型類。 Int
可以通過多種方式製作爲Monoid
,包括加0和加1.我們如何選擇哪一個用於Int
的Monoid
實例?最好不要表達偏好,並使用newtype
s來啓用或不使用運行時成本。複述the standard library:
-- introduce a type Sum with a constructor Sum which wraps an Int, and an extractor getSum which gives you back the Int
newtype Sum = Sum { getSum :: Int }
instance Monoid Sum where
(Sum x) `mappend` (Sum y) = Sum (x + y)
mempty = Sum 0
newtype Product = Product { getProduct :: Int }
instance Monoid Product where
(Product x) `mappend` (Product y) = Product (x * y)
mempty = Product 1
隨着data
創建新數據類型和聲明構造它:
data NewData = NewDataConstructor
隨着type
定義只是一個別名:
type MyChar = Char
在type
情況下,你可以傳遞的價值MyChar
類型功能期望Char
,反之亦然,但您不能這樣做data MyChar = MyChar Char
。
type
作品就像let
:它允許你給一個可重複使用的名字的東西,但事情總是工作一樣,如果你有內聯的定義。所以
type ℝ = Double
f :: ℝ -> ℝ -> ℝ
f x y = let x2 = x^2
in x2 + y
行爲完全相同的方式一樣
f' :: Double -> Double -> Double
f' x y = x^2 + y
如:你可以在你的代碼的任何地方與f'
,反之亦然更換f
;沒有什麼會改變。
OTOH,均爲data
和newtype
創建不透明抽象。它們更像是一個OO中的類構造函數:即使一些值是實施僅僅根據單個數字,它不一定行爲就像這樣一個數字。例如,
newtype Logscaledℝ = LogScaledℝ { getLogscaled :: Double }
instance Num LogScaledℝ where
LogScaledℝ a + LogScaledℝ b = LogScaledℝ $ a*b
LogScaledℝ a - LogScaledℝ b = LogScaledℝ $ a/b
LogScaledℝ a * LogScaledℝ b = LogScaledℝ $ a**b
這裏,雖然Logscaledℝ
數據是明智的仍然只是一個Double
數,它清楚地表現從Double
不同。
- 1. Rails數據類型有什麼區別?
- 2. Haskell中的類型和數據類型有什麼區別?
- 3. `overload`關鍵字有什麼區別嗎?
- 4. 「流類型」套接字和「數據報」套接字類型有什麼區別?
- 5. jquery中的數據和數據類型有什麼區別?
- 6. dict.keys()中的關鍵字與關鍵字有什麼區別?
- 7. 基元類和基元數據類型有什麼區別?
- 8. oracle sql中的join關鍵字和inner join關鍵字有什麼區別?
- 9. `pandas.read_csv`中`str`和`object`數據類型有什麼區別?
- 10. MySQL中BLOB和TEXT數據類型有什麼區別?
- 11. MySQL BOOL和BOOLEAN列數據類型有什麼區別?
- 12. Cassandra數據類型中的INT和VARINT有什麼區別?
- 13. sqlalchemy的數據類型中的Varchar和String有什麼區別?
- 14. 創建結構的「數據」和「類型」有什麼區別?
- 15. webassembly數據類型中的uint32和i32有什麼區別?
- 16. postgresql中decimal和numeric數據類型有什麼區別
- 17. 函數參數中的struct關鍵字有什麼區別?
- 18. 「throw」關鍵字和「Write-Error-ErrorAction Stop」之間有什麼區別?
- 19. C#中的覆蓋和新關鍵字有什麼區別?
- 20. C#中的enum關鍵字和C有什麼區別?
- 21. 關鍵字:is和==有什麼區別python
- 22. c和C++之間關鍵字static有什麼區別?
- 23. noexcept關鍵字和_NOEXCEPT宏有什麼區別?
- 24. 使用box關鍵字和Box :: new之間有什麼區別?
- 25. java和super關鍵字有什麼區別?
- 26. 關鍵字'Private'和'Final'有什麼區別?
- 27. 使用synchronized關鍵字和鎖之間有什麼區別
- 28. 泛型類型和泛型類型定義有什麼區別?
- 29. scope「import」和「pom」類型依賴關係有什麼區別?
- 30. MVC模型,數據和數據庫有什麼區別?