Chr*_*non 35 io monads haskell readfile
我在Haskell中编写了一堆代码来创建文本索引.top函数如下所示:
index :: String -> [(String, [Integer])]
index a = [...]
Run Code Online (Sandbox Code Playgroud)
现在我想给这个函数一个从文件读取的字符串:
index readFile "input.txt"
Run Code Online (Sandbox Code Playgroud)
哪个不起作用,因为readFile的类型为FilePath - > IO String.
无法将预期类型'String'与推断类型'IO String'匹配
我看到错误,但我找不到任何类型的函数:
IO String -> String
Run Code Online (Sandbox Code Playgroud)
我想成功的关键在于Monads的某些地方,但我找不到解决问题的方法.
cth*_*ops 42
您可以轻松编写一个调用readFile操作的函数,并将结果传递给索引函数.
readAndIndex fileName = do
text <- readFile fileName
return $ index text
Run Code Online (Sandbox Code Playgroud)
但是,IO monad会污染使用它的所有内容,因此该函数具有以下类型:
readAndIndex :: FilePath -> IO [(String, [Integer])]
Run Code Online (Sandbox Code Playgroud)
Tir*_*pen 29
有一个很好的理由说明没有这样的功能.
Haskell具有功能纯度的概念.这意味着当使用相同的参数调用时,函数将始终返回相同的结果.允许IO 的唯一地方是IO monad.
如果有*功能
index :: IO String -> String
Run Code Online (Sandbox Code Playgroud)
然后我们可以通过调用突然在任何地方执行IO操作,例如:
index (launchMissiles >> deleteRoot >> return "PWNd!")
Run Code Online (Sandbox Code Playgroud)
功能纯度是一个非常有用的功能,我们不想丢失,因为它允许编译器更自由地重新排序和内联函数,它们可以在不改变语义的情况下引发到不同的内核,并且它还给程序员一个意义安全性,因为如果你能知道一个函数可以做什么,不能从它的类型做什么.
*其实有是这样的功能.它被称为unsafePerformIO
并且它被称为非常非常好的理由.除非你100%确定你在做什么,否则不要使用它!
R. *_*des 16
好吧,你无法摆脱IO
monad部分IO String
.这意味着你必须让你的函数返回IO [(String, [Integer])]
.
我建议学习更多关于monad的知识,但是现在你可以逃脱这个liftM
功能了:
liftM index (readFile "input.txt")
Run Code Online (Sandbox Code Playgroud)
liftM
有这个签名:
liftM :: Monad m => (a -> b) -> m a -> m b
Run Code Online (Sandbox Code Playgroud)
它需要一个非monadic函数并将其转换为monadic函数.
fmap index $ readFile "input.txt"
Run Code Online (Sandbox Code Playgroud)
要么
readFile "input.txt" >>= return . index
Run Code Online (Sandbox Code Playgroud)
你可能想看看monad和functor