[英]Why is the output of this Haskell function an IO String instead of a String
我正在通過learningyouahaskell.com學習Haskell,並想在完成輸入/輸出模塊之前測試一些概念。 盡管看起來很簡單,但我仍無法用谷歌或笨拙的方式解決這個問題。
當我嘗試運行以下代碼時
getName = do
name <- getLine
return name
即使name絕對是String
, getName
的輸出也將成為IO String
類型而不是String
類型的元素
通過閱讀文檔和其他StackVverflow的問題,當我將getName
聲明為函數時(當我直接在main
上直接使用bind <-操作時,就沒有問題了),我無法弄清楚為什么會發生這種情況。
return
函數在概念上與C ++,Java和Python等語言中的return
函數並不相同。 return :: Monad m => a -> ma
接受a
(這里是String
),並產生ma
(這里IO a
)。
該do
記號是syntacticual糖。 如果我們對聲明不加糖,那么您寫道:
getName = getLine >>= (\name -> return name)
或更清潔的:
getName = getLine >>= return
因此,綁定函數(>>=) :: Monad m => ma -> (a -> mb) -> mb
具有第一個操作數ma
和第二個功能a -> mb
並產生mb
。 由於getLine :: IO String
是IO String
,因此這意味着m
與IO
相同,而a
與String
相同。 return :: Monad m => a -> ma
,清楚地表明b
與a
相同。
那么這里的IO
是什么。 一個經常使用的隱喻就是食譜之一 。 在此隱喻中, IO a
是一組指令,當您遵循這些指令時,將獲得a
。 但這並不意味着該食譜是a
。
(>>=)
這里基本上是說,左手邊有一個制作a
的配方,右手邊有個將a
轉換成要制作b
的配方的函數,因此我們可以構造一個要點b
的配方與這兩個。
人們經常會問如何解開一個a
出的IO a
,但在概念上它使沒有太大意義。 您不能從食譜中“解包”蛋糕來制作蛋糕。 您可以按照說明做蛋糕。 遵循指示是main
最終操作。 因此,我們可以構造一個主要的(長)配方。 但是我們不能解開價值觀。
嚴格來說,有一個函數unsafePerformIO :: IO a -> a
可以做到這一點。 但是強烈建議不要使用它。 Haskell中的函數應該是純函數,這意味着對於相同的輸入,我們總是檢索相同的輸出。 getLine
本身是純函數,因為它總是產生相同的配方( IO String
)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.