[英]A Haskell function of type: IO String-> String
我在 Haskell 中編寫了一堆代碼來創建文本索引。 頂部函數如下所示:
index :: String -> [(String, [Integer])]
index a = [...]
現在我想給這個函數一個從文件中讀取的字符串:
index readFile "input.txt"
這是行不通的,因為 readFile 的類型是 FilePath -> IO String。
無法將預期類型“字符串”與推斷類型“IO 字符串”匹配
我看到錯誤,但我找不到任何類型的函數:
IO String -> String
我想成功的關鍵在於一些 Monads 下的某個地方,但我找不到解決問題的方法。
您可以輕松編寫一個調用 readFile 操作的函數,並將結果傳遞給您的索引函數。
readAndIndex fileName = do
text <- readFile fileName
return $ index text
但是,IO monad 會污染使用它的所有內容,因此該函數具有以下類型:
readAndIndex :: FilePath -> IO [(String, [Integer])]
沒有這樣的功能是有充分理由的。
Haskell 有函數純度的概念。 這意味着當使用相同的參數調用時,函數將始終返回相同的結果。 唯一允許 IO 的地方是在 IO monad 內部。
如果有*一個函數
index :: IO String -> String
然后我們可以通過調用突然在任何地方執行 IO 操作,例如:
index (launchMissiles >> deleteRoot >> return "PWNd!")
函數純度是我們不想失去的一個非常有用的特性,因為它允許編譯器更自由地重新排序和內聯函數,它們可以在不改變語義的情況下被觸發到不同的內核,它也給了程序員一種感覺安全性,因為如果你能從它的類型中知道一個函數可以做什么和不能做什么。
*其實有這樣的功能。 它被稱為unsafePerformIO
並且有非常非常好的理由。 除非您 100% 確定自己在做什么,否則不要使用它!
好吧,您無法擺脫IO String
的IO
monad 部分。 這意味着你必須讓你的函數返回IO [(String, [Integer])]
。
我建議學習更多關於 monad 的知識,但現在你可以使用liftM
函數:
liftM index (readFile "input.txt")
liftM
有這個簽名:
liftM :: Monad m => (a -> b) -> m a -> m b
它接受一個非一元函數並將其轉換為一元函數。
fmap index $ readFile "input.txt"
或者
readFile "input.txt" >>= return . index
你可能想研究 monad 和 functors
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.