类型为 IO String-> 的 Haskell 函数细绳

发布于 2024-08-09 19:10:28 字数 466 浏览 9 评论 0原文

我在 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

来日方长 2024-08-16 19:10:28

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

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

然而,IO monad 污染了所有使用它的东西,所以这个函数的类型是:

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

You can easily enough write a function that calls the readFile action, and passes the result to your index function.

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

However, the IO monad taints everything that uses it, so this function has the type:

readAndIndex :: FilePath -> IO [(String, [Integer])]
烙印 2024-08-16 19:10:28

没有这样的功能是有充分理由的。

Haskell 有函数纯度的概念。这意味着当使用相同的参数调用函数时,函数将始终返回相同的结果。 唯一允许 IO 的地方是 IO monad 内部。

如果有*一个函数,

index :: IO String -> String

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

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

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

* 实际上有这样的函数。它被称为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

index :: IO String -> String

then we could suddenly do IO actions anywhere by calling, for example:

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

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!

山人契 2024-08-16 19:10:28

好吧,你无法摆脱 IO String 的 IO monad 部分。这意味着您必须使函数返回 IO [(String, [Integer])] 。

我建议更多地了解 monad,但现在您可以使用 liftM 函数:

liftM index (readFile "input.txt")

liftM 具有以下签名:

liftM :: Monad m => (a -> b) -> m a -> m b

它采用非 monadic 函数并将其转换为一元函数。

Well you cannot get rid of the IO monad part of IO String. That means you will have to make your function return IO [(String, [Integer])].

I recommend learning more about monads, but for now you can get away with the liftM function:

liftM index (readFile "input.txt")

liftM has this signature:

liftM :: Monad m => (a -> b) -> m a -> m b

It takes a non-monadic function and transforms it into a monadic function.

人心善变 2024-08-16 19:10:28
fmap index $ readFile "input.txt"

或者

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

你可能想研究 monad 和 functors

fmap index $ readFile "input.txt"

or

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

You may want to look into monad and functors

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文