另一個 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 操作,因為它必須是。為了更清楚地說明這一點,你可能應該繼續閱讀教程。
