类型为 IO String-> 的 Haskell 函数细绳
我在 Haskell 中编写了一堆代码来创建文本索引。顶部函数如下所示:
index :: String -> [(String, [Integer])]
index a = [...]
现在我想给这个函数一个从文件中读取的字符串:
index readFile "input.txt"
这将不起作用,因为 readFile 的类型为 FilePath -> IO 字符串。
无法匹配预期类型“String” 针对推断类型“IO String”
我看到了错误,但找不到任何类型的函数:
IO String -> String
我猜成功的关键在于某些 Monad 下的某个地方,但我找不到解决问题的方法。
I wrote a bunch of code in Haskell to create an index of a text. The top function looks like this:
index :: String -> [(String, [Integer])]
index a = [...]
Now I want to give this function a String read from a file:
index readFile "input.txt"
Which won't work because readFile is of type FilePath -> IO String.
Couldn't match expected type 'String'
against inferred type 'IO String'
I see the error, but I can't find any function with type:
IO String -> String
I guess the key to success lies somewhere under some Monads, but I could not find a way to solve my problem.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您可以轻松编写一个调用 readFile 操作的函数,并将结果传递给索引函数。
然而,IO monad 污染了所有使用它的东西,所以这个函数的类型是:
You can easily enough write a function that calls the readFile action, and passes the result to your index function.
However, the IO monad taints everything that uses it, so this function has the type:
没有这样的功能是有充分理由的。
Haskell 有函数纯度的概念。这意味着当使用相同的参数调用函数时,函数将始终返回相同的结果。 唯一允许 IO 的地方是 IO monad 内部。
如果有*一个函数,
那么我们可以通过调用突然在任何地方执行 IO 操作,例如:
函数纯度是一个非常有用的功能,我们不想失去它,因为它允许编译器重新排序和内联函数更加自由,它们可以在不改变语义的情况下被触发到不同的核心,并且它也给程序员一种安全感,因为如果你可以从函数的类型知道函数可以做什么和不能做什么。
* 实际上有这样的函数。它被称为
unsafePerformIO
,并且这样称呼是有非常非常充分理由的。 除非您 100% 确定自己在做什么,否则不要使用它!There is a very good reason why there is no such function.
Haskell has the notion of functional purity. This means that a function will always return the same result when called with the same parameters. The only place where IO is allowed is inside the IO monad.
If there was* a function
then we could suddenly do IO actions anywhere by calling, for example:
Functional purity is a very useful feature that we don't want to lose, since it allows the compiler to reorder and inline functions much more freely, they can be sparked off to different cores without changing the semantics and it also gives the programmers a sense of security since if you can know what a function can and can't do from it's type.
* Actually there is such a function. It's called
unsafePerformIO
and it's called that for very, very good reasons. Do not use it unless you're 100% sure of what you are doing!好吧,你无法摆脱 IO String 的 IO monad 部分。这意味着您必须使函数返回 IO [(String, [Integer])] 。
我建议更多地了解 monad,但现在您可以使用
liftM
函数:liftM
具有以下签名:它采用非 monadic 函数并将其转换为一元函数。
Well you cannot get rid of the
IO
monad part ofIO String
. That means you will have to make your function returnIO [(String, [Integer])]
.I recommend learning more about monads, but for now you can get away with the
liftM
function:liftM
has this signature:It takes a non-monadic function and transforms it into a monadic function.
或者
你可能想研究 monad 和 functors
or
You may want to look into monad and functors