Haskell函数类型:IO String-> String

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)

  • 这只是一个小句子:"IO monad玷污了使用它的一切".我确实认为是这种情况,但很高兴看到它现在得到证实.谢谢^^ (5认同)

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%确定你在做什么,否则不要使用它!

  • 我会说"不要使用它,除非你对你正在做的事情有200%的肯定",或者更简单,"不要". (14认同)
  • 我会说unsafePerformIO的最佳用途是向一些应该总是返回相同内容的进程进行shell.即标准库本身不支持的系统计算. (6认同)
  • 添加到我在浏览SO时发现的旧评论:对FFI也很有用 (4认同)

R. *_*des 16

好吧,你无法摆脱IOmonad部分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函数.


Jam*_*mes 9

fmap index $ readFile "input.txt"
Run Code Online (Sandbox Code Playgroud)

要么

readFile "input.txt" >>= return . index
Run Code Online (Sandbox Code Playgroud)

你可能想看看monad和functor