簡體   English   中英

一個 Haskell 函數類型:IO String-> String

[英]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 StringIO 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM