您的位置:首页 > 其它

Haskell笔记1

2012-07-13 14:44 239 查看
Haskell笔记1
1. 类型

类型



lists

ghci> head [1,2,3,4]1

ghci> head ['a','b','c']'a'

tuples

ghci> (1964, "Labyrinths")

(1964,"Labyrinths")

2. 函数

函数



take

ghci> take 2 [1,2,3,4,5]

[1,2]

drop

ghci> drop 3 [1,2,3,4,5]

[4,5]

fst

ghci> fst (1,'a')

1

snd

ghci> snd (1,'a')

'a'

head

ghci> head (drop 4 "azerty")

't'

lines

ghci> lines "the quick\nbrown fox\njumps"

["the quick","brown fox","jumps"]

null

ghci> :type null

null :: [a] -> Boolghci> :type (||)(||) :: Bool -> Bool -> Bool

mod

isOdd n = mod n 2 == 1

print

ghci> print (myDrop 2 "abcd")"cd"

last

ghci> last [1,2,3,4,5]

5

ghci> last "baz"

'z'

3. 逻辑语句

分支和循环



If..then..else

myDrop n xs = if n <= 0 || null xs

then xs

else myDrop (n - 1) (tail xs)

We'll refer to the expressions after the then and else keywords as “branches”. The branches must have the same types; the if expression will also have this type. An expression such as if True then 1 else "foo" has different
types for its branches, so it is ill typed and will be rejected by a compiler or interpreter.

Recall that Haskell is an expression-oriented language. In an imperative language, it can make sense to omit the else branch from an if, because we're working with statements, not expressions. However, when we're working
with expressions, an if that was missing an else wouldn't have a result or type if the predicate evaluated to False, so it would be nonsensical.

4. Ghci环境

函数

例子

:load

ghci> :load add.hs

[1 of 1] Compiling Main ( add.hs, interpreted )

Ok, modules loaded: Main.

:cd

ghci> :cd /tmp

:type

ghci> :type lines

lines :: String -> [String]

ghci> :type last

last :: [a] -> a

5. 其他

概念

解释

结合性

In Haskell, function application is left associative. This is best illustrated by example: the expression a b c d is equivalent to (((a b) c) d).

It's pretty clear that there's something going on with an Int and some lists, but why are there two -> symbols in the signature? Haskell groups this chain of arrows from right to left; that is, -> is right-associative.
If we introduce parentheses, we can make it clearer how this type signature is interpreted.

等号

When you see an = symbol in Haskell code, it represents “meaning”: the name on the left is defined to be the expression on the right.

函数的纯洁性

A side effect introduces a dependency between the global state of the system and the behaviour of a function. For example, let's step away from Haskell for a moment and think about an imperative programming language.
Consider a function that reads and returns the value of a global variable. If some other code can modify that global variable, then the result of a particular application of our function depends on the current value of the global variable. The function
has a side effect, even though it never modifies the variable itself.

Side effects are essentially invisible inputs to, or outputs from, functions. In Haskell, the default is for functions to not have side effects: the result of a function depends only on the inputs that we explicitly provide.
We call these functions pure; functions with side effects are impure.

If a function has side effects, we can tell by reading its type signature: the type of the function's result will begin with IO.

ghci> :type readFile

readFile :: FilePath -> IO String

imperative language

Python,perl

variable

In Haskell, a variable provides a way to give a name to an expression. Once a variable is bound to (i.e. associated with) a particular expression, its value does not change: we can always use the name of the variable
instead of writing out the expression, and get the same result either way.

Polymorphism

When a function has type variables in its signature, indicating that some of its arguments can be of any type, we call the function polymorphic.

subtype polymorphism

Since Haskell isn't an object oriented language, it doesn't provide subtype polymorphism.

parametric polymorphism

This kind of polymorphism is called parametric polymorphism.

coercion polymorphism

Also common is coercion polymorphism, which allows a value of one type to be implicitly converted into a value of another type. Many languages provide some form of coercion polymorphism: one example is automatic conversion
between integers and floating point numbers. Haskell deliberately avoids even this kind of simple automatic coercion.

type signature

We can now write a type signature for the myDrop function that we defined earlier.

-- file: ch02/myDrop.hs

myDrop :: Int -> [a] -> [a]

6. 高级

概念

解释

Lazy evaluation

In Haskell, the subexpression 1 + 2 is not reduced to the value 3. Instead, we create a “promise” that when the value of the expression isOdd (1 + 2) is needed, we'll be able to compute it. The record that we use to track
an unevaluated expression is referred to as a thunk. This is all that happens: we create a thunk, and defer the actual evaluation until it's really needed. If the result of this expression is never subsequently used, we will not compute its value at all.

Short circuiting

Many languages need to treat the logical-or operator specially so that it short circuits if its left operand evaluates to True. In Haskell, (||) is an ordinary function: non-strict evaluation builds this capability into
the language.

thunk

The result of applying a function may be a thunk.

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: