“数据”与“数据”之间有什么区别?和“类型”关键字? [英] What's the difference between "data" and "type" keywords?

查看:164
本文介绍了“数据”与“数据”之间有什么区别?和“类型”关键字?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

数据类型关键字总是让我困惑。

我想知道 data type 以及如何使用它们。

解决方案 类型声明类型同义词 。类型同义词是现有类型的新名称。例如,这就是 String 是如何定义的在标准库中:

  type String = [Char] 

字符串是一个 Char s的列表。 GHC将在编译时用 [Char] 替换程序中 String 的所有用法。



明确地说,字符串 字面上是 Char code>秒。这只是一个别名。您可以使用字符串值中的所有标准列表函数:

   -  - 长度:: [a]  - > Int 
ghci>长度haskell
7
- 反向:: [a] - > [a]
ghci>反向功能性
lanoitcnuf






data 声明一个新数据类型,与类型同义词不同,它与其他类型不同。数据类型有许多构造函数定义您的类型的可能情况。例如,这是如何定义 Bool 标准库

  data Bool = False | True 

Bool 值可以是 True False 。数据类型支持模式匹配,允许您对数据类型的值执行运行时案例分析。

  yesno :: Bool  - >字符串
yesno True =是
yesno False =no

data 类型可以有多个构造函数(如 Bool ),可以由其他类型参数化,可以包含其他类型他们,并可以递归引用自己。这里有一个例外的模型来证明这一点。 错误包含 a 类型的错误消息,并且可能是导致它的错误。

 数据错误a =错误{值:: a,原因::可能错误} 
类型ErrorWithMessage =错误字符串

myError1,myError2 :: ErrorWithMessage
myError1 =错误woops没有
myError2 =错误myError1被抛出(只是myError1)

认识到 data 声明了一个与系统中任何其他类型不同的新类型是很重要的。如果 String 已被声明为 data type 包含<$ c $的列表c> Char s(而不是类型同义词),您将无法使用任何列表函数。

  data String = MkString [Char] 
myString = MkString ['h','e','l','l','o']
myReversedString = reverse myString - 类型错误






还有一种类型声明: newtype 。这很像 data 声明 - 它引入了一种独立于任何其他类型的新数据类型,并且可以进行模式匹配 - 除了仅限于一个构造函数领域。换句话说, newtype 是包装现有类型的 data 类型。



重要的区别是 newtype 成本:编译器承诺 newtype 的表现方式与其包装的类型相同。打包或解包 newtype 不需要运行时间成本。这使得 newtype 对于使管理(而不是结构)区分值有用。



newtype s与类型类很好地交互。例如,考虑 Monoid ,这是一种类型的类,它可以将元素( mappend )和一个特殊的'empty '元素( mempty )。 Int 可以通过很多方式变成 Monoid ,包括加0和乘1.我们如何选择哪一个可用于 Monoid Int实例的实例?最好不要表达首选项,并使用 newtype s来启用没有运行时成本的使用。解释标准库

   - 引入一个带有构造函数Sum的Sum类,它包装一个Int和一个提取器getSum, 
newtype Sum = Sum {getSum :: Int}
实例Monoid Sum其中
(Sum x)`mappend`(Sum y)= Sum(x + y)
mempty =总和0

newtype Product = Product {getProduct :: Int}
实例Monoid Product其中
(Product x)`mappend`(Product y)= Product(x * y)
mempty =产品1


The data and type keywords always confuse me.

I want to know what is the difference between data and type and how to use them.

解决方案

type declares a type synonym. A type synonym is a new name for an existing type. For example, this is how String is defined in the standard library:

type String = [Char]

String is another name for a list of Chars. GHC will replace all usages of String in your program with [Char] at compile-time.

To be clear, a String literally is a list of Chars. It's just an alias. You can use all the standard list functions on String values:

-- length :: [a] -> Int
ghci> length "haskell"
7
-- reverse :: [a] -> [a]
ghci> reverse "functional"
"lanoitcnuf"


data declares a new data type, which, unlike a type synonym, is different from any other type. Data types have a number of constructors defining the possible cases of your type. For example, this is how Bool is defined in the standard library:

data Bool = False | True

A Bool value can be either True or False. Data types support pattern matching, allowing you to perform a runtime case-analysis on a value of a data type.

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

data types can have multiple constructors (as with Bool), can be parameterised by other types, can contain other types inside them, and can recursively refer to themselves. Here's a model of exceptions which demonstrates this; an Error a contains an error message of type a, and possibly the error which caused it.

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)

It's important to realise that data declares a new type which is apart from any other type in the system. If String had been declared as a data type containing a list of Chars (rather than a type synonym), you wouldn't be able to use any list functions on it.

data String = MkString [Char]
myString = MkString ['h', 'e', 'l', 'l', 'o']
myReversedString = reverse myString  -- type error


There's one more variety of type declaration: newtype. This works rather like a data declaration - it introduces a new data type separate from any other type, and can be pattern matched - except you are restricted to a single constructor with a single field. In other words, a newtype is a data type which wraps up an existing type.

The important difference is the cost of a newtype: the compiler promises that a newtype is represented in the same way as the type it wraps. There's no runtime cost to packing or unpacking a newtype. This makes newtypes useful for making administrative (rather than structural) distinctions between values.

newtypes interact well with type classes. For example, consider Monoid, the class of types with a way to combine elements (mappend) and a special 'empty' element (mempty). Int can be made into a Monoid in many ways, including addition with 0 and multiplication with 1. How can we choose which one to use for a possible Monoid instance of Int? It's better not to express a preference, and use newtypes to enable either usage with no runtime cost. Paraphrasing 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

这篇关于“数据”与“数据”之间有什么区别?和“类型”关键字?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆