Ben*_*son 22
type声明一个类型同义词.类型同义词是现有类型的新名称.例如,这是在标准库中String定义的方式:
type String = [Char]
Run Code Online (Sandbox Code Playgroud)
String是Chars 列表的另一个名称.GHC将取代所有使用String与您的程序[Char]在编译时.
要清楚,String 字面意思是Char s 的列表.这只是一个别名.您可以在String值上使用所有标准列表函数:
-- length :: [a] -> Int
ghci> length "haskell"
7
-- reverse :: [a] -> [a]
ghci> reverse "functional"
"lanoitcnuf"
Run Code Online (Sandbox Code Playgroud)
data声明一种新的数据类型,与类型同义词不同,它与任何其他类型不同.数据类型有许多构造函数,用于定义类型的可能情况.例如,这是在标准库中Bool定义的方式:
data Bool = False | True
Run Code Online (Sandbox Code Playgroud)
甲Bool值可以是True或False.数据类型支持模式匹配,允许您对数据类型的值执行运行时大小写分析.
yesno :: Bool -> String
yesno True = "yes"
yesno False = "no"
Run Code Online (Sandbox Code Playgroud)
data类型可以有多个构造函数(如同Bool),可以通过其他类型进行参数化,可以在其中包含其他类型,并且可以递归地引用自己.这是一个例外模型,证明了这一点; 一个Error a包含类型的错误消息a,并且可能引起它的误差.
data Error a = Error { value :: a, cause :: Maybe (Error a) }
type ErrorWithMessage = Error String
myError1, myError2 :: ErrorWithMessage
myError1 = Error "woops" Nothing
myError2 = Error "myError1 was thrown" (Just myError1)
Run Code Online (Sandbox Code Playgroud)
重要的是要认识到data声明一种新的类型,它与系统中的任何其他类型不同.如果String已声明为包含 s 列表的data类型(而不是类型同义词),则无法在其上使用任何列表函数.Char
data String = MkString [Char]
myString = MkString ['h', 'e', 'l', 'l', 'o']
myReversedString = reverse myString -- type error
Run Code Online (Sandbox Code Playgroud)
还有一种类型声明:newtype.这非常类似于data声明 - 它引入了与任何其他类型分开的新数据类型,并且可以进行模式匹配 - 除了您被限制为具有单个字段的单个构造函数.换句话说,a newtype是data包装现有类型的类型.
最重要的区别是成本的newtype:编译器的承诺,一个newtype被以同样的方式,因为它包装的类型表示.打包或拆包没有运行时成本newtype.这newtype对于在值之间进行管理(而不是结构)区分很有用.
newtype与类型类很好地交互.例如,考虑Monoid一下类型的类,它有一种方法可以组合elements(mappend)和一个特殊的'empty'元素(mempty).Int可以通过Monoid多种方式制作,包括添加0和乘以1.我们如何选择哪一个用于可能的Monoid实例Int?最好不要表达首选项,并使用newtypes来启用任何使用而不需要运行时成本.解释标准库:
-- 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
Run Code Online (Sandbox Code Playgroud)