另一个 Haskell 教程/语言基础/解答
| Haskell | |
|---|---|
| |
| 另一个 Haskell 教程 | |
| 序言 | |
| 介绍 | |
| 入门 | |
| 语言基础 (解答) | |
| 类型基础 (解答) | |
| IO (解答) | |
| 模块 (解答) | |
| 高级语言 (解答) | |
| 高级类型 (解答) | |
| 单子 (解答) | |
| 高级 IO | |
| 递归 | |
| 复杂度 | |
它绑定得更紧密;实际上,函数应用比任何其他东西都绑定得更紧密。为了看到这一点,我们可以做一些类似的事情
示例
Prelude> sqrt 3 * 3 5.19615
如果乘法绑定得更紧密,结果将是 3。
解答:snd (fst ((1,'a'),"foo"))。这是因为首先我们要取元组的第一半:(1,'a'),然后从这里我们要取第二半,只得到'a'。
如果你尝试了fst (snd ((1,'a'),"foo")),你会得到一个类型错误。这是因为snd的应用会让你得到fst "foo"。但是,字符串“foo”不是元组,所以你不能将fst应用于它。
解答:map Data.Char.isLower "aBCde"
解答:length (filter Data.Char.isLower "aBCde")
解答:foldr max 0 [5,10,2,8,1]。
你也可以使用foldl。foldr的情况更容易解释:我们将每个cons替换为max的应用,并将空列表替换为 0。因此,最内层的应用将取 0 和列表的最后一个元素(如果存在)的最大值。然后,下一个内层的应用将返回之前最大值和倒数第二个元素的最大值。这将持续下去,将当前的最大值一直带到列表的开头。
在foldl的情况下,我们可以认为这是按顺序查看列表中的每个元素。我们从“状态” 0 开始。我们取出第一个元素并检查它是否大于我们当前的状态。如果是,我们将当前状态替换为该数字,然后继续。这种情况发生在每个元素上,因此最终会返回最大元素。
解答:fst (head (tail [(5,'b'),(1,'c'),(6,'a')]))
我们可以将斐波那契函数定义为
fib 1 = 1 fib 2 = 1 fib n = fib (n-1) + fib (n-2)
我们也可以使用显式的if语句,比如
fib n =
if n == 1 || n == 2
then 1
else fib (n-1) + fib (n-2)
两者都可以接受,但第一个在 Haskell 中可能更自然。
我们可以定义
然后输入代码
mult a 0 = 0
mult a 1 = a
mult a b =
if b < 0
then 0 - mult a (-b)
else a + mult a (b-1)
请注意, 和 我们进行递归操作并不重要。我们也可以将其定义为:
mult 0 b = 0
mult 1 b = b
mult a b =
if a < 0
then 0 - mult (-a) b
else b + mult (a-1) b
我们可以将 my_map 定义为
my_map f [] = [] my_map f (x:xs) = f x : my_map f xs
回顾一下,my_map 函数应该将函数 f 应用于列表中的每个元素。在列表为空的情况下,没有元素可以应用函数,因此我们只返回空列表。
在列表非空的情况下,它是一个元素 x 后跟一个列表 xs。假设我们已经正确地将 my_map 应用于 xs,那么我们剩下的唯一工作就是将 f 应用于 x,然后将结果组合在一起。这就是第二行所做的。
以下代码出现在 Numbers.hs 中。唯一棘手的部分是 getNums 和 showFactorials 中的递归调用。
module Main
where
import System.IO
main = do
nums <- getNums
putStrLn ("The sum is " ++ show (sum nums))
putStrLn ("The product is " ++ show (product nums))
showFactorials nums
getNums = do
putStrLn "Give me a number (or 0 to stop):"
num <- getLine
if read num == 0
then return []
else do rest <- getNums
return ((read num :: Int):rest)
showFactorials [] = return ()
showFactorials (x:xs) = do
putStrLn (show x ++ " factorial is " ++
show (factorial x))
showFactorials xs
factorial 1 = 1
factorial n = n * factorial (n-1)
getNums 的思路正如提示中所述。对于 showFactorials,我们首先考虑递归调用。假设我们有一个数字列表,第一个数字是 x。首先,我们打印出显示阶乘的字符串。然后,我们打印出剩余部分,因此进行了递归调用。但是,在空列表的情况下我们该怎么办呢?显然我们已经完成了,所以我们不需要做任何事情,因此我们只需 return ()。
请注意,这必须是 return () 而不是 (),因为如果我们只是写 showFactorials [] = (),那么这将不是一个 IO 操作,因为它需要是一个 IO 操作。有关这方面的更多说明,你应该继续阅读教程。
