我會試着從一個簡單的例子開始。假設這是我們想要做的:
- 打開一個文件,其中包含一個整數列表並返回它。
- 排序此列表
- 我們也扭轉名單
- 打印結果屏幕上
讓我們也說,我們有這些功能,我們可以使用:
getContent :: IO [Int]
sort :: [Int] -> [Int]
reverse :: [Int] -> [Int]
show :: a -> String
putStrLn :: String -> IO()
剛所以我們很清楚,我會對這些功能說一句話:
getContent
:我編了這個函數,但是如果有這個函數就是它的簽名(你可以使用getContent = return [3,7,2,1]
進行測試)。我相信你之前已經看到過這樣的簽名,至少隱約瞭解到,因爲它的確簽名不能只是getContent :: [Int]
。
sort
:這是一個在Data.List模塊中定義的函數,使用簡單:sort [3,1,2]
回報[1,2,3]
reverse
:在Data.List模塊中還定義:reverse [1,3,2]
回報[2,3,1]
show
:不需要輸入任何東西,只需使用它:show 11
返回字符串"11"
; show [1,2,3]
返回字符串"[1,2,3]"
等
- putStrLn:需要一個字符串,把它放到屏幕上,並返回IO(),現在又說,因爲它的IO其簽名不能只是
putStrLn :: Stiring ->()
。
好的,現在我們有了我們需要的所有功能來創建我們的程序,現在的問題是關於將這些功能連接在一起。讓我們開始與連接功能:
getContent :: IO [Int]
與sort :: [Int] -> [Int]
我認爲,如果你得到這個角色,你會很容易得到休息爲好。所以,問題是因爲getContent
返回IO [Int]
而不僅僅是[Int]
,你不能忽略或擺脫IO
部分並將其推入sort
。也就是說,這是你不能做連接這些功能是什麼:
sort (getRidOfIO getContent)
這裏就是>>= :: m a -> (a -> m b) -> m b
操作就派上用場了。現在請注意m
,a
和b
是類型變量因此,如果我們爲[Int]
和b
爲[Int]
替代m
爲IO
,a
,我們得到的signagure:
>>= :: IO [Int] -> ([Int] -> IO [Int]) -> IO [Int]
那些getContent
再看一看和sort
職能和他們的簽名,並試圖思考他們將如何適應>>=
。我相信你會注意到你可以直接使用getContent
作爲>>=
的第一個參數。到目前爲止,>>=
將要做的是將[Int]
取出getContent
,並將其推入作爲第二個參數提供的函數中。但是第二個參數的功能是什麼?我們不能直接使用sort :: [Int] -> [Int]
,我們可以嘗試下最好的事情是
\listOfInts -> sort listOfInts
,但仍然有簽名[Int] -> [Int]
,這樣並沒有太大幫助。這裏是另一個英雄來到劇本的地方,
return :: a -> m a
。
再次,a
和m
是類型變量,可以替代他們,我們會盡快
return :: [Int] -> IO [Int]
因此增加\listOfInts -> sort listOfInts
和return
在一起,我們將得到:
\listOfInts -> return $ sort listOfInts :: [Int] -> IO [Int]
哪個正是我們想要作爲>>=
的第二個參數。所以讓我們用我們的膠水一起finaly連接getContent
和sort
:
getContent >>= (\listOfInts -> return $ sort listOfInts)
這是同樣的事情(使用do
符號):
do listOfInts <- getContent
return $ sort listOfInts
那裏,那是最末尾可怕的部分。現在可能是aha時刻之一,試着想想我們剛剛組成的連接的結果類型是什麼。我會爲你破壞它,......
getContent >>= (\listOfInts -> return $ sort listOfInts)
是IO [Int]
的類型。讓我們總結一下:我們採取了IO [Int]
類型的東西和[Int] -> [Int]
類型的東西,將這兩件事粘在一起,再次獲得IO [Int]
類型的東西!
現在繼續嘗試完全一樣的東西:以我們剛剛創建的IO [Int]
對象一起膠水(使用>>=
和return
)與reverse :: [Int] -> [Int]
。
我覺得我寫的太多了,但是讓我知道是否有什麼不清楚的地方,或者如果你需要其他幫助。
什我到目前爲止所描述可以是這個樣子:
getContent :: IO [Int]
getContent = return [5,2,1,7]
main :: IO()
main = do
listOfInts <- getContent
return $ sort listOfInts
return() -- This is only to sattisfy the signature of main
強制性鏈接:http://www.haskell.org/tutorial/以防萬一這是繞過 - 「溫和」的當然是相對的。 – 2011-03-05 17:43:02
我也學習了一個偉大的哈斯克爾,雖然只有幾天。 – Orbit 2011-03-05 17:45:51
除了需要使用'do'符號或者刪除賦值('<--')並移動到使用bind('>> =')之外,您不能將'data'命名爲保留字。 – 2011-03-05 19:19:27