Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between the "data" and "type" keywords?

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.

like image 660
Lin Jiayin Avatar asked Oct 24 '15 09:10

Lin Jiayin


People also ask

What is difference between keyword and data type?

The primary difference between the text datatype and the keyword datatype is that text fields are analyzed at the time of indexing, and keyword fields are not. What that means is, text fields are broken down into their individual terms at indexing to allow for partial matching, while keyword fields are indexed as is.

What is data keyword?

Beyond the distinction between variable and constant is the distinction between different types of data. Some types of data are numbers. Some are letters or, more generally, characters. The computer needs a way to identify and use these different kinds.

What is the difference between keyword and data type in Java?

Java Data-types:- These are Keywords in java. They are also known as Primitive data-types or Native data-types. Data-types in any language specify the type of data to be stores and the size of memory to be allocated.

What is data type and keyword in C?

Octal values, hexadecimal values, and decimal values can be stored in int data type in C. We can determine the size of the int data type by using the sizeof operator in C. Unsigned int data type in C is used to store the data values from zero to positive numbers but it can't store negative values like signed int.


1 Answers

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 a) }
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
like image 175
Benjamin Hodgson Avatar answered Oct 16 '22 00:10

Benjamin Hodgson