这里所有的例子都在
GHC上执行通过。这是一个免费的编译器,可以直接下载,提供ghci的互交环境,和python一样:)
首先来看一个haskell的函数:
average :: Float -> Float -> Float -> Float
average a b c = (a + b + c) / 3.0
这个函数的作用很明显,我们关注的是它的语法形式,双冒号之前的是函数名,之后函数的主体部分会再次重复这个名字。双冒号之后是参数列表,用->来连接,最后一个float是返回值,之前的都是参数。现在看第二行,这个是函数的定义部分,abc分别对应声明部分三个参数,等号之后则是函数的逻辑部分。刚刚开始的时候会觉得这样的语法十分怪异,等习惯了之后。。。还是觉得十分恶心。。。呵呵。。。
再看一个例子:
and :: Bool -> Bool -> Bool
and a b = a == b
这个函数的作用是做逻辑与操作。haskell也支持if-else-then和switch形式的语句,所以上面的函数也可以写成:
and1 :: Bool -> Bool -> Bool
and1 a b = if a == b then True
else False
和
and2 :: Bool -> Bool -> Bool
and2 a b | a == b = True
| otherwise = False
Haskell可以自己定义类型,先看一个例子:
type Colour = String
type ColourPoint = (Int, Int, Colour)
changeColour :: ColourPoint -> Colour -> ColourPoint
changeColour (x, y, oldColour) newColour = (x, y, newColour)
第一行和第二行分别定义了两个类型,第三行开始changeColour是一个函数,接受一个point然后更改其颜色。注意定义部分,(x, y, oldColour)对应的是参数列表中的ColourPoint,newColour对应的是Colour。
引用自定义对象的时候也不一定非要指出具体的对象内容,象这样:
equals :: ColourPoint -> ColourPoint -> Bool
equals a b = if a == b then True
else False
也是可以的。另外,当对象很复杂而我们又要修改其中的值的时候,不需要把整个对象呈现出来,Haskell支持通配符帮助我们简化代码:
equalPos :: ColourPoint -> ColourPoint -> Bool
equalPos (a,b,_)(c,d,_)= a==c && b==d
下划线省略了我们不关心的部分。
进一步深入之前,来看看Haskell的数组。语法和c类似,[ ]表示的是数组,不过[1,2,3,4]可以写成[1..4],解释器会自行翻译。数组支持一个添加元素的操作,1:[2,3,4]的结果和上面是一样的,冒号把元素添加到数组头上去。这是一个例子:
enumFromTo :: Int -> Int ->[Int]
enumFromTo m n | m > n = []
| otherwise = m:(enumFromTo (m+1) n)
这个函数接受两个整数分别代表上限以及下限,返回一个整型数组,所以enumFromTo 1 4的作用实际上和[1..4]是一样的。注意这是一个递归形式的函数,实际的过程是1:2:3:4:[]。
现在来扩展一下这个函数,让函数可以指定想前进的步数而不只是仅仅加1:
myenumFromToBy :: Int -> Int -> Int -> [Int]
myenumFromToBy m n k | m > n = []
| otherwise = m:myenumFromToBy (m+k) n k
不过这个函数只能前进,不能后退,再改一下,我们有了第三个版本:
myenumFromToBy1 :: Int -> Int -> Int -> [Int]
myenumFromToBy1 m n k | k > 0 = myenumFromToBy m n k
| otherwise = if m<0 then []
else m:myenumFromToBy1 (m+k) n k
ok,这样这个函数基本上就可以任意前进后退了。注意,上面的函数都是没有什么括号啊,分号之类的分隔符的。haskell和python一样,采用layout的机制,用空格等对齐来格式代码。所以当编译不通过的时候,往往就是对齐的问题。目前haskell没有什么好的IDE可以用, UltraEdit为Haskell提供了一个语法高亮的插件,可以用用看。
下一次,我们更深入的讨论haskell的递归,这个是所有functional language最骄傲的特性。
首先来看一个haskell的函数:
average :: Float -> Float -> Float -> Float
average a b c = (a + b + c) / 3.0
这个函数的作用很明显,我们关注的是它的语法形式,双冒号之前的是函数名,之后函数的主体部分会再次重复这个名字。双冒号之后是参数列表,用->来连接,最后一个float是返回值,之前的都是参数。现在看第二行,这个是函数的定义部分,abc分别对应声明部分三个参数,等号之后则是函数的逻辑部分。刚刚开始的时候会觉得这样的语法十分怪异,等习惯了之后。。。还是觉得十分恶心。。。呵呵。。。
再看一个例子:
and :: Bool -> Bool -> Bool
and a b = a == b
这个函数的作用是做逻辑与操作。haskell也支持if-else-then和switch形式的语句,所以上面的函数也可以写成:
and1 :: Bool -> Bool -> Bool
and1 a b = if a == b then True
else False
和
and2 :: Bool -> Bool -> Bool
and2 a b | a == b = True
| otherwise = False
Haskell可以自己定义类型,先看一个例子:
type Colour = String
type ColourPoint = (Int, Int, Colour)
changeColour :: ColourPoint -> Colour -> ColourPoint
changeColour (x, y, oldColour) newColour = (x, y, newColour)
第一行和第二行分别定义了两个类型,第三行开始changeColour是一个函数,接受一个point然后更改其颜色。注意定义部分,(x, y, oldColour)对应的是参数列表中的ColourPoint,newColour对应的是Colour。
引用自定义对象的时候也不一定非要指出具体的对象内容,象这样:
equals :: ColourPoint -> ColourPoint -> Bool
equals a b = if a == b then True
else False
也是可以的。另外,当对象很复杂而我们又要修改其中的值的时候,不需要把整个对象呈现出来,Haskell支持通配符帮助我们简化代码:
equalPos :: ColourPoint -> ColourPoint -> Bool
equalPos (a,b,_)(c,d,_)= a==c && b==d
下划线省略了我们不关心的部分。
进一步深入之前,来看看Haskell的数组。语法和c类似,[ ]表示的是数组,不过[1,2,3,4]可以写成[1..4],解释器会自行翻译。数组支持一个添加元素的操作,1:[2,3,4]的结果和上面是一样的,冒号把元素添加到数组头上去。这是一个例子:
enumFromTo :: Int -> Int ->[Int]
enumFromTo m n | m > n = []
| otherwise = m:(enumFromTo (m+1) n)
这个函数接受两个整数分别代表上限以及下限,返回一个整型数组,所以enumFromTo 1 4的作用实际上和[1..4]是一样的。注意这是一个递归形式的函数,实际的过程是1:2:3:4:[]。
现在来扩展一下这个函数,让函数可以指定想前进的步数而不只是仅仅加1:
myenumFromToBy :: Int -> Int -> Int -> [Int]
myenumFromToBy m n k | m > n = []
| otherwise = m:myenumFromToBy (m+k) n k
不过这个函数只能前进,不能后退,再改一下,我们有了第三个版本:
myenumFromToBy1 :: Int -> Int -> Int -> [Int]
myenumFromToBy1 m n k | k > 0 = myenumFromToBy m n k
| otherwise = if m<0 then []
else m:myenumFromToBy1 (m+k) n k
ok,这样这个函数基本上就可以任意前进后退了。注意,上面的函数都是没有什么括号啊,分号之类的分隔符的。haskell和python一样,采用layout的机制,用空格等对齐来格式代码。所以当编译不通过的时候,往往就是对齐的问题。目前haskell没有什么好的IDE可以用, UltraEdit为Haskell提供了一个语法高亮的插件,可以用用看。
下一次,我们更深入的讨论haskell的递归,这个是所有functional language最骄傲的特性。