Haskell笔记1

来源:互联网 发布:软件代码保护 编辑:程序博客网 时间:2024/05/29 09:33

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.