An overview of

The type system is an important part of Haskell and is closely related to functions. Functions are usually introduced in introductory books.

The type system in Haskell has three characteristics.

  • Strong typing: Casts such as those in Javascript are completely unacceptable in Haskell
  • Static typing: The compiler knows the type of every value and expression at compile time.
  • Type inference: In most cases the Haskell compiler can deduce the type of an expression

There are many related concepts, such as Type, TypeClass,Kind, etc. The text will briefly introduce the content of Type TypeClass.

Type the Type

We can see the type of any expression in GHCI by using the :t command

Prelude>:t 'a'
'a' :: Char 
Prelude>:t True
True :: Bool
Prelude>:t "Hello"
"Hello"::[Char]
Prelude>:t 1
1::Num p => p
Prelude>:t (==)
(==) :: Eq a => a -> a -> Bool
Copy the code

Here are some very common things, like:

  • TrueisBoolType, also belonging toBoolThere are also typesFalse
  • 'a'CharThe type of

There are other common types

  • IntThe number range is dependent on the number of bits the operating system has in GHC, and for 32-bit operating systems and GHC, the range is- 2 ^ 31to2 ^ 31-1.
  • IntegerUnbounded signed integer, efficiency ratioIntlow
  • FloatSingle-precision floating point number
  • DoubleA double – precision floating – point number

In addition to these more common things, there are some special ones. For example (==) :: Eq a => a -> Bool the :: symbol is used to declare the type of the expression on its right side, which can be read as “type as”. The => symbol stands for “type constraint”, meaning that A belongs to the TypeClass of Eq. (==) :: Eq a => a -> a -> Bool For (==), we need two arguments a, a belonging to Eq TypeClass, and the result returns a Bool. Reading this, I think you will naturally have two questions —

  1. ->What said
  2. TypeClassWhat is it?

When declaring function types, -> is used to separate arguments, which we’ll briefly cover here, but let’s focus on TypeClass.

Type class TypeClass

A type that belongs to a type class must implement the behavior that the type class describes — the functions that the type class declares. This sentence sounds like a mouthful, but let’s start with GHCI’s built-in: I command.

The equality type class Eq

Enter: I Eq we get a long list of information about the type class Eq. Let’s look at some of them.

The definition of Eq describes two functions that its members implement, both of which take two parameters to produce a Bool. In the following information, we can see that Bool,Char,Double,Int, etc. are instances of Eq, so we can perform (==),(/=) operations on these types of data.

Prelude>1 1 (= =)
True
Prelude>(= =)'a' 'a'
True
Prelude> (==) True False
False
Prelude>1 1 (/ =)
False
Prelude>(/ =)'a' 'a'
False
Prelude> (/=) True False
True
Copy the code

It is also possible to use infix style functions

Prelude>1 = = 1
True
Prelude>1 / = 1
False
Copy the code

The ordered type class Ord

If the Eq class describes the behavior of its member types for equality and inequality, the Ord class can perform (<), (>), (<=), (>=) and other operations for size comparison.

Prelude>1 0 (>)
True
Prelude>1 0 (<)
False
Prelude> (>) 'a' 'z'
False
Copy the code

Enumeration Type Type Enum

Enum is a very interesting type class. Its member types are continuously enumerable. We have a successer and a preesor for each value, which can be retrieved by succ and pred, respectively. So let’s say 1 is preceded by 0 and then 2 and 2 is preceded by 1 and then 3. And so on, for any value, we can deduce what the next n values are. This brings up the Range introduced in Learning Haskell (1) : Hello Haskell. Through / 2.. Represents a list of positive integers greater than 2, followed by prime traversal. Enum members include Bool, Char, Int, Integer, etc.

Prelude> succ False
True
Prelude> pred True
False
Prelude> ['a'.'x']
"abcdefghijklmnopqrstuvwx"
Prelude>8] [1..,2,3,4,5,6,7,8 [1]Copy the code

Bounded type classes are Bounded

A Bounded type class that describes data types with live boundaries. For example, the Int type mentioned earlier has a lower bound of -2^31 and a upper bound of 2^31-1 for 32-bit operating systems and GHC. The minBound and maxBound functions are used to get the bounds of a type.

Prelude> minBound :: Int- 2147483648.Prelude> maxBound :: Char'\ 1114111'Prelude> maxBound :: Bool  
True  
Prelude> minBound :: Bool  
False
Copy the code

The numeric type class Num

The number type class describes the general behavior of numbers, such as adding, subtracting, multiplying +,-,*, taking the absolute value abs and so on.

Prelude>Abs (1.2)
1.2
Prelude> 1.2 * 1.3
1.56
Copy the code

One of the more interesting functions is fromInteger. Because of Haskell’s strong typing, 1.2::Float and 2::Integer cannot be computed directly, but fromInteger can be used to convert Integer data to the more general Num a => a type and then computed.

Prelude> num1 = 2::Integer
Prelude>Num2 = 1.2: : Float
Prelude> num2 + num1<interactive>:137:8: error: • Couldn't match expected type 'Float' with actual type 'Integer' • In the second argument of '(+)', Namely 'num1' In the expression: num2 + num1 In an equation for 'it' : it = num2 + num1Prelude> num2 + (fromInteger num1)
3.2
Copy the code

A similar function is fromIntegral.

Benefits of the type system

As for the benefits of the type system, there are many summaries on the Internet, such as:

  • Improve application performance

  • Detect errors and improve code robustness

  • Reduce the difficulty and risk of refactoring

  • .

Another benefit to Haskell is that it makes it easier to retrieve documents. Haskell’s Hoogle engine makes it easy to search for related functions by function type.

For example, if we want to search for a function that takes a Float argument and returns a value of type Int, we can search by Float -> Int.

This way of searching the API provides convenience and, to some extent, shapes the programmer’s mind.

To summarize

To a computer, the data a program is manipulating is nothing more than a string of meaningless binary numbers. But for humans, dividing data into different types is much more readable and manageable. For high-level programming languages, the presence of types makes data easier to process.

Different types of data sometimes have similar behaviors. For example, Int and Char data, although of different types. But can enumerate and do equal judgment. The need for such similar behavior abstractions gave birth to TypeClass. The relationship between Type and TypeClass, if you want to draw an analogy to object-oriented programming, is similar to that between a class and an interface.

As this article draws to a close, Haskell’s type system is complex and powerful. It took me a long time to gradually understand something when I was learning. Later, I will record my learning through one or two articles.