Gentle Introduction to Haskell 98
-
Introduction
-
Start with some sample lists to use in test cases:
-
The type Bool is already defined in the Prelude so there is no need to define it here.
-
data Tree a = Leaf a | Branch (Tree a) (Tree a) deriving Show
The following typings are implied by this declaration. As before, this is not valid Haskell syntax.
-
Since type synonyms are part of the type language only, it's hard to write a program which shows what they do. Essentially, they are like macros for the type language. They can be used interchangeably with their definition:
-
Warning: brackets in Haskell are used in three different sorts of expressions: lists, as in [a,b,c], sequences (distinguished by the ..), as in [1..2], and list comprehensions (distinguished by the bar: |), as in [x+1 | x <- xs, x > 1].
-
Section: 3 Functions
第 3 节 函数
add :: Int -> Int -> Int
add x y = x+y
e1 :: Int
e1 = add 1 2
This Int -> Int is the latter part of the signature of add:
-
Haskell has both identifiers, like x, and operators, like +. These are just two different types of syntax for variables. However, operators are by default used in infix notation.
-
Observing lazy evaluation can present difficulties. The essential question is does an expression get evaluated?. While in theory using a non-terminating computation is the way evaluation issues are examined, we need a more practical approach. In expressions, Haskell uses error to denote bottom. Evaluation of error will halt execution and print the attached error message. The error function can be used to create stub functions for program components which have not been written yet or as a value to insert into data structures where a data value is required but should never be used.
-
Now for details of pattern matching. We use [Int] instead of [a] since the only value of type [a] is [].
-
The function take using a case statement instead of multiple equations:
-
Names in the basic class structure of Haskell cannot be hidden (they are in PreludeCore) so we have to modify the names used in the tutorial.
-
Section 6.1
-
import IO (isEOFError)
Both putStr and getLine are actually in the prelude.
-
import IO
Section 7.3
-
No examples are provided for 5.1 or 5.2. The standard Prelude contains many instance declarations which illustrate the Eq, Ord, and Enum classes.
-
We have actually been using the derived Show instances all along for printing out trees and other structures we have defined. The code in the tutorial for the Eq and Ord instance of Tree is created implicitly by the deriving clause so there is no need to write it here.
-
Section 9.1 Monadic Classes
-
import Complex
Section: 10 Numbers
Section: 10.1 Numeric Class Structure
Section: 10.2 Constructed Numbers
第 10 节 数值
第 10.1 节 数值类的结构
第 10.2 节 构造的数值类型
Here's a brief summary of Haskell numeric classes.
-
import Complex
Section: 10.4 Default Numeric Types
第 10.4 节 默认数值类型
Ambiguous contexts arise frequently in numeric expressions. When an expression which produces a value with a general type, such as 1 (same as fromInteger 1; the type is (Num a) => a), with another expression which consumes the type, such as show or toInteger, ambiguity arises. This ambiguity can be resolved using expression type signatures, but this gets tedious fast! Assigning a type to the top level of an ambiguous expression does not help: the ambiguity does not propagate to the top level.
-
Section 11
-
import Tree ( Tree(Leaf,Branch), fringe )
import qualified Fringe ( fringe )
See Fringe.lhs
-
import TreeADT
See TreeADT.lhs
-
-- f g = (g 'a',g []) -- This won't typecheck.
Section: 12.2 Overloaded Numerals
第 12.2 节 重载的数字字面量
Overloaded numerics were covered previously - here is one more example. sum is a prelude function which sums the elements of a list.
-
import Array
Section: 13 Arrays
Section: 13.1 Index Types
第 13 节 数组
第 13.1 节 索引类型
Arrays are built on the class Ix. Here are some quick examples of Ix: