diff options
Diffstat (limited to 'zh-cn')
-rw-r--r-- | zh-cn/haskell-cn.html.markdown | 117 |
1 files changed, 56 insertions, 61 deletions
diff --git a/zh-cn/haskell-cn.html.markdown b/zh-cn/haskell-cn.html.markdown index fae8a456..8904970f 100644 --- a/zh-cn/haskell-cn.html.markdown +++ b/zh-cn/haskell-cn.html.markdown @@ -13,7 +13,8 @@ Haskell 是一门实用的函数式编程语言,因其 Monads 与类型系统 ```haskell -- 单行注释以两个减号开头 -{- 多行注释像这样被一个闭合的块包围 +{- 多行注释像这样 + 被一个闭合的块包围 -} ---------------------------------------------------- @@ -46,9 +47,9 @@ not False -- True 1 < 10 -- True -- 在上面的例子中,`not` 是一个接受一个参数的函数。 --- Haskell 不需要括号来调用函数。所有的参数都只是在函数名之后列出来。 +-- Haskell 不需要括号来调用函数,所有的参数都只是在函数名之后列出来 -- 因此,通常的函数调用模式是: --- func arg1 arg2 arg3... +-- func arg1 arg2 arg3... -- 你可以查看函数部分了解如何自行编写。 -- 字符串和字符 @@ -65,11 +66,11 @@ not False -- True ---------------------------------------------------- --- 数组和元组 +-- 列表和元组 ---------------------------------------------------- --- 一个数组中的每一个元素都必须是相同的类型 --- 下面两个数组等价: +-- 一个列表中的每一个元素都必须是相同的类型。 +-- 下面两个列表等价 [1, 2, 3, 4, 5] [1..5] @@ -81,34 +82,32 @@ not False -- True [5..1] -- 这样不行,因为 Haskell 默认递增 [5,4..1] -- [5, 4, 3, 2, 1] --- 数组下标 +-- 列表下标 [0..] !! 5 -- 5 --- 在 Haskell 你可以使用无限数组 -[1..] -- 一个含有所有自然数的数组 +-- 在 Haskell 你可以使用无限列表 +[1..] -- 一个含有所有自然数的列表 --- 无限数组的原理是,Haskell 有“惰性求值”。 +-- 无限列表的原理是,Haskell 有“惰性求值”。 -- 这意味着 Haskell 只在需要时才会计算。 --- 所以当你获取数组的第 1000 项元素时,Haskell 会返回给你: - +-- 所以当你获取列表的第 1000 项元素时,Haskell 会返回给你: [1..] !! 999 -- 1000 - --- Haskell 计算了数组中第 1 至 1000 项元素,但这个无限数组中剩下的元素还不存在。 +-- Haskell 计算了列表中第 1 至 1000 项元素,但这个无限列表中剩下的元素还不存在。 -- Haskell 只有在需要时才会计算它们。 --- 连接两个数组 +-- 连接两个列表 [1..5] ++ [6..10] --- 往数组头增加元素 +-- 往列表头增加元素 0:[1..5] -- [0, 1, 2, 3, 4, 5] --- 其它数组操作 +-- 其它列表操作 head [1..5] -- 1 tail [1..5] -- [2, 3, 4, 5] init [1..5] -- [1, 2, 3, 4] last [1..5] -- 5 --- 数组推导 +-- 列表推导 (list comprehension) [x*2 | x <- [1..5]] -- [2, 4, 6, 8, 10] -- 附带条件 @@ -125,6 +124,7 @@ snd ("haskell", 1) -- 1 ---------------------------------------------------- -- 3. 函数 ---------------------------------------------------- + -- 一个接受两个变量的简单函数 add a b = a + b @@ -137,7 +137,7 @@ add 1 2 -- 3 -- 你也可以使用反引号中置函数名: 1 `add` 2 -- 3 --- 你也可以定义不带字母的函数名,这样你可以定义自己的操作符 +-- 你也可以定义不带字母的函数名,这样你可以定义自己的操作符。 -- 这里有一个做整除的操作符 (//) a b = a `div` b 35 // 4 -- 8 @@ -147,36 +147,36 @@ fib x | x < 2 = x | otherwise = fib (x - 1) + fib (x - 2) --- 模式匹配与 Guard 类似 --- 这里给出了三个不同的 fib 定义 +-- 模式匹配与 Guard 类似。 +-- 这里给出了三个不同的 fib 定义。 -- Haskell 会自动调用第一个符合参数模式的声明 fib 1 = 1 fib 2 = 2 fib x = fib (x - 1) + fib (x - 2) --- 元组的模式匹配: +-- 元组的模式匹配 foo (x, y) = (x + 1, y + 2) --- 数组的模式匹配 --- 这里 `x` 是列表中第一个元素,`xs` 是列表剩余的部分 +-- 列表的模式匹配 +-- 这里 `x` 是列表中第一个元素,`xs` 是列表剩余的部分。 -- 我们可以实现自己的 map 函数: myMap func [] = [] myMap func (x:xs) = func x:(myMap func xs) --- 匿名函数带有一个反斜杠,后面跟着所有的参数。 +-- 匿名函数带有一个反斜杠,后面跟着所有的参数 myMap (\x -> x + 2) [1..5] -- [3, 4, 5, 6, 7] -- 在 fold(在一些语言称 为`inject`)中使用匿名函数 --- foldl1 意味着左折叠 (fold left), 并且使用列表中第一个值作为累加器的初始值 +-- foldl1 意味着左折叠 (fold left), 并且使用列表中第一个值作为累加器的初始值。 foldl1 (\acc x -> acc + x) [1..5] -- 15 ---------------------------------------------------- -- 4. 其它函数 ---------------------------------------------------- --- 部分调用: --- 如果你调用函数时没有给出所有参数,它就被“部分调用” --- 它将返回一个接受余下参数的函数 +-- 部分调用 +-- 如果你调用函数时没有给出所有参数,它就被“部分调用”。 +-- 它将返回一个接受余下参数的函数。 add a b = a + b foo = add 10 -- foo 现在是一个接受一个数并对其加 10 的函数 foo 5 -- 15 @@ -185,8 +185,8 @@ foo 5 -- 15 foo = (+10) foo 5 -- 15 --- 函数组合 --- (.) 函数把其它函数链接到一起 +-- 函列表合 +-- (.) 函数把其它函数链接到一起。 -- 例如,这里 foo 是一个接受一个值的函数。 -- 它对接受的值加 10,并对结果乘以 5,之后返回最后的值。 foo = (*5) . (+10) @@ -195,9 +195,9 @@ foo = (*5) . (+10) foo 5 -- 75 -- 修正优先级 --- Haskell 有另外一个函数 `$` 可以改变优先级 --- `$` 使得 Haskell 先计算其右边的部分,然后调用左边的部分 --- 你可以使用 `$` 来移除多余的括号 +-- Haskell 有另外一个函数 `$` 可以改变优先级。 +-- `$` 使得 Haskell 先计算其右边的部分,然后调用左边的部分。 +-- 你可以使用 `$` 来移除多余的括号。 -- 修改前 (even (fib 7)) -- true @@ -220,13 +220,13 @@ even $ fib 7 -- true True :: Bool -- 函数也有类型 --- `not` 接受一个布尔型返回一个布尔型: +-- `not` 接受一个布尔型返回一个布尔型 -- not :: Bool -> Bool --- 这是接受两个参数的函数: +-- 这是接受两个参数的函数 -- add :: Integer -> Integer -> Integer --- 当你定义一个值,声明其类型是一个好做法: +-- 当你定义一个值,声明其类型是一个好做法 double :: Integer -> Integer double x = x * 2 @@ -250,30 +250,29 @@ case args of _ -> putStrLn "bad args" -- Haskell 没有循环,它使用递归 --- map 对一个数组中的每一个元素调用一个函数: - +-- map 对一个列表中的每一个元素调用一个函数 map (*2) [1..5] -- [2, 4, 6, 8, 10] --- 你可以使用 map 来编写 for 函数: +-- 你可以使用 map 来编写 for 函数 for array func = map func array --- 调用: +-- 调用 for [0..5] $ \i -> show i --- 我们也可以像这样写: +-- 我们也可以像这样写 for [0..5] show -- 你可以使用 foldl 或者 foldr 来分解列表 -- foldl <fn> <initial value> <list> foldl (\x y -> 2*x + y) 4 [1,2,3] -- 43 --- 等价于: +-- 等价于 (2 * (2 * (2 * 4 + 1) + 2) + 3) --- foldl 从左开始,foldr 从右: +-- foldl 从左开始,foldr 从右 foldr (\x y -> 2*x + y) 4 [1,2,3] -- 16 --- 现在它等价于: +-- 现在它等价于 (2 * 3 + (2 * 2 + (2 * 1 + 4))) ---------------------------------------------------- @@ -293,9 +292,9 @@ say Green = "You are Green!" data Maybe a = Nothing | Just a -- 这些都是 Maybe 类型: -Just "hello" -- of type `Maybe String` -Just 1 -- of type `Maybe Int` -Nothing -- of type `Maybe a` for any `a` +Just "hello" -- `Maybe String` 类型 +Just 1 -- `Maybe Int` 类型 +Nothing -- 对任意 `a` 为 `Maybe a` 类型 ---------------------------------------------------- -- 8. Haskell IO @@ -321,7 +320,7 @@ main' = interact countLines -- 你可以认为一个 `IO ()` 类型的值是表示计算机做的一系列操作,类似命令式语言。 -- 我们可以使用 `do` 声明来把动作连接到一起。 --- 举个列子: +-- 举个列子 sayHello :: IO () sayHello = do putStrLn "What is your name?" @@ -336,7 +335,8 @@ sayHello = do -- 让我们来更进一步理解刚才所使用的函数 `getLine` 是怎样工作的。它的类型是: -- getLine :: IO String --- 你可以认为一个 `IO a` 类型的值代表了一个运行时会生成一个 `a` 类型值的程序(可能还有其它行为)。 +-- 你可以认为一个 `IO a` 类型的值代表了一个运行时会生成一个 `a` 类型值的程序。 +-- (可能伴随其它行为) -- 我们可以通过 `<-` 保存和重用这个值。 -- 我们也可以实现自己的 `IO String` 类型函数: action :: IO String @@ -348,8 +348,7 @@ action = do -- `return` 不是关键字,只是一个普通函数 return (input1 ++ "\n" ++ input2) -- return :: String -> IO String --- 我们可以像调用 `getLine` 一样调用它: - +-- 我们可以像调用 `getLine` 一样调用它 main'' = do putStrLn "I will echo two lines!" result <- action @@ -358,29 +357,25 @@ main'' = do -- `IO` 类型是一个 "Monad" 的例子。 -- Haskell 通过使用 Monad 使得其本身为纯函数式语言。 --- 任何与外界交互的函数(即 IO)都在它的类型声明中标记为 `IO` --- 这告诉我们什么样的函数是“纯洁的”(不与外界交互,不修改状态) ,什么样的函数不是 “纯洁的” - +-- 任何与外界交互的函数(即 IO)都在它的类型声明中标记为 `IO`。 +-- 这告诉我们什么样的函数是“纯洁的”(不与外界交互,不修改状态) , +-- 什么样的函数不是 “纯洁的”。 -- 这个功能非常强大,因为纯函数并发非常容易,由此在 Haskell 中做并发非常容易。 - ---------------------------------------------------- -- 9. Haskell REPL ---------------------------------------------------- -- 键入 `ghci` 开始 REPL。 -- 现在你可以键入 Haskell 代码。 --- 任何新值都需要通过 `let` 来创建: - +-- 任何新值都需要通过 `let` 来创建 let foo = 5 --- 你可以查看任何值的类型,通过命令 `:t`: - +-- 你可以通过命令 `:t` 查看任何值的类型 >:t foo foo :: Integer -- 你也可以运行任何 `IO ()`类型的动作 - > sayHello What is your name? Friend! |