[英]Intermediate values in haskell io
我正在學習Haskell,作為練習,我編寫了一個程序,該程序讀取整數並打印下一個:
main = do
line_with_n_in_it <- getLine
putStrLn $ show $ (read line_with_n_in_it :: Int) + 1
但是,對於我來說必須明確命名我所讀的行似乎很愚蠢。
如果我寫
main = do
putStrLn $ show $ (read getLine :: Int) + 1
runghc
抱怨說read
需要一個String
,但是getLine
提供了一個IO String
。 因此,據我了解,似乎這個神奇的<-
運算符將IO String
轉換為String
。
是否有其他運算符或函數可以讓我簡單地內聯<-
運算符? 因此,如果magic
是我的魔術功能,那么我可以將新程序編寫為
main = do
putStrLn $ show $ (read $ magic getLine :: Int) + 1
您應該閱讀有關monads(和IO monad)的信息
一個良好的開端這里
問題是您必須從monad中“提取”值,而這並不是“完全”函數調用。
您的第一個代碼是正確的,您從monad中提取了一些值
readedString <- getLine
然后用它
putStrLn $ "Readed: " ++ readedString
您可以避免使用“命名行”,但是總的來說,可以為此寫上好名字。
為了避免命名,您必須編寫一些monadic函數,然后進行綁定
getLine >>= putStrLn . show . (+1) . read
但是,再次,我建議您閱讀有關monads(和IO monad)的信息。
順便說一句, <-
運算符“等於” >>=
運算符, 此處詳細介紹。
Haskell明確禁止這種行為的事實正是使它如此有價值的原因-您不能混合使用純代碼和IO混亂的代碼。
神奇的<-
運算符是用於單鍵綁定的語法糖。 例如,可以使用>>=
運算符(發音為“ bind”)顯式地重寫原始函數:
main = do
n <- getLine
putStrLn $ show $ (read n :: Int) + 1
===
main = getLine >>= \n -> putStrLn $ show $ (read n :: Int) + 1
對您來說<-
似乎很神奇的事實是一件好事-它不是標准的haskell語法,而是糖。 使用后者編寫函數應該更有意義。
至於為什么它起作用,我可以為您提供針對IO monad的簡單說明,並建議您閱讀“ 學好了Haskell for Great Good!” 的有關monad的章節(或整本書,如果您真的很新!),以增強您的理解。
開始了。 getLine
從IO
讀取一個String
,對不對? 但這意味着調用的結果被“標記為IO”。 這是一個包裝在IO
上下文中的String
,就像普通的String
一樣,我們無法對其進行操作。 這樣做會違反參照透明性 ,因為IO
上下文(即您正在閱讀的內容)可能會更改。 基本上,魔術<-
運算符所做的就是從IO
上下文中“拉出”純String
值,並允許您對其進行操作。 更明確地說, >>=
運算符將執行IO
操作( getLine
),並執行將String
轉換為新IO
操作(在轉換后的示例中為lambda表達式)並返回該新IO
操作的函數。 這是將IO
表達式鏈接在一起,“挖掘”其內部值,對其進行操作,然后將其重新包裝在IO
。 一般而言,單子詞不是我(或任何人)可以在SO答案中向您詳細解釋的東西,但是如果您打算繼續學習Haskell,我強烈建議您閱讀LYAH-這是一本很棒的書,並且會讓您快速上手。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.