Haskell函数类型:IO String->串

时间:2009-11-04 17:24:23

标签: haskell io monads readfile

我在Haskell中编写了一堆代码来创建文本索引。 top函数如下所示:

index :: String -> [(String, [Integer])]
index a = [...]

现在我想给这个函数一个从文件读取的字符串:

index readFile "input.txt"

这不起作用,因为readFile的类型为FilePath - > IO字符串。

  

无法匹配预期类型'String'   反对推断类型'IO String'

我看到了错误,但我找不到任何类型的函数:

IO String -> String

我认为成功的关键在某些Monads下,但我找不到解决问题的方法。

4 个答案:

答案 0 :(得分:40)

您可以轻松编写一个调用readFile操作的函数,并将结果传递给索引函数。

readAndIndex fileName = do
    text <- readFile fileName
    return $ index text

但是,IO monad会污染使用它的所有内容,因此该函数的类型为:

readAndIndex :: FilePath -> IO [(String, [Integer])]

答案 1 :(得分:27)

有一个很好的理由说明没有这样的功能。

Haskell具有功能纯度的概念。这意味着当使用相同的参数调用时,函数将始终返回相同的结果。允许IO的唯一位置在IO monad内。

如果有*功能

index :: IO String -> String

然后我们可以通过调用突然在任何地方执行IO动作,例如:

index (launchMissiles >> deleteRoot >> return "PWNd!")

功能纯度是一个非常有用的功能,我们不想丢失,因为它允许编译器更自由地重新排序和内联函数,它们可以在不改变语义的情况下引发到不同的核心,并且它还给出了程序员有一种安全感,因为如果你能知道一个函数可以做什么,也不能从它的类型中做到。

*实际上这样的功能。它被称为unsafePerformIO,它被称为非常非常的好理由。 除非你100%确定自己在做什么,否则不要使用它!

答案 2 :(得分:15)

嗯,你无法摆脱IO的{​​{1}} monad部分。这意味着您必须让函数返回IO String

我建议您详细了解monad,但现在您可以使用IO [(String, [Integer])]函数:

liftM

liftM index (readFile "input.txt") 有这个签名:

liftM

它需要一个非monadic函数并将其转换为monadic函数。

答案 3 :(得分:8)

fmap index $ readFile "input.txt"

readFile "input.txt" >>= return . index

您可能需要查看monad和functors