haskell - "data"和 "type"关键字有什么区别?

标签 haskell keyword

datatype 关键字总是让我感到困惑。

我想知道datatype之间有什么区别以及如何使用它们。

最佳答案

type 声明一个类型同义词。类型同义词是现有类型的新名称。例如,String 的定义方式是 in the standard library :

type String = [Char]

StringChar 列表的另一个名称。 GHC 将在编译时用 [Char] 替换程序中所有 String 的用法。

需要明确的是,String字面意思是一个Char列表。这只是一个别名。您可以对 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 值可以是 TrueFalse。数据类型支持模式匹配,允许您对数据类型的值执行运行时案例分析。

yesno :: Bool -> String
yesno True = "yes"
yesno False = "no"

data 类型可以有多个构造函数(与 Bool 一样),可以由其他类型参数化,可以在其中包含其他类型,并且可以递归引用自身。这是一个异常(exception)模型,它演示了这一点; 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)

重要的是要认识到 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成本:编译器 promise newtype 的表示方式与其类型相同包裹。打包或解压 newtype 没有运行时成本。这使得 newtype 对于在值之间进行管理(而不是结构)区分非常有用。

newtype 与类型类交互良好。例如,考虑 Monoid,它是一种类型类,具有组合元素 (mappend) 和特殊“空”元素 (mempty) 的方式。 Int 可以通过多种方式变成 Monoid,包括与 0 相加和与 1 相乘。我们如何选择将哪一个用于可能的 Monoid Int 的实例?最好不要表达偏好,并使用 newtype 来启用任一用途,而无需运行时成本。释义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

关于haskell - "data"和 "type"关键字有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33316533/

相关文章:

python 3 : Formatting a string with multiple same keywords but unique strings to replace them

scala - 为什么 "lazy"是关键字而不是标准库类型?

java - 如何访问Lucene索引中记录的关键字?

list - Haskell 范围表示法生成列表。意外输出

haskell - 具有多个数据构造函数的单一类型与多个类型

haskell - 您可以编写一个类型函数来反转约束吗?

Haskell getContents 等待 EOF

haskell - 是否可以在 cabal 包中将库的示例可执行文件指定为可选?

c# - 如何在 C# 中检查一个字符串不是关键字或类型

c++ - C++ 中的 NULL 和 __null 有什么区别?