简体   繁体   English

一个 Haskell 函数类型:IO String-> String

[英]A Haskell function of type: IO String-> String

I wrote a bunch of code in Haskell to create an index of a text.我在 Haskell 中编写了一堆代码来创建文本索引。 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.这是行不通的,因为 readFile 的类型是 FilePath -> IO String。

Couldn't match expected type 'String' against inferred type 'IO String'无法将预期类型“字符串”与推断类型“IO 字符串”匹配

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.我想成功的关键在于一些 Monads 下的某个地方,但我找不到解决问题的方法。

You can easily enough write a function that calls the readFile action, and passes the result to your index function.您可以轻松编写一个调用 readFile 操作的函数,并将结果传递给您的索引函数。

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

However, the IO monad taints everything that uses it, so this function has the type:但是,IO monad 会污染使用它的所有内容,因此该函数具有以下类型:

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

There is a very good reason why there is no such function.没有这样的功能是有充分理由的。

Haskell has the notion of functional purity. Haskell 有函数纯度的概念。 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.唯一允许 IO 的地方是在 IO monad 内部。

If there was* a function如果有*一个函数

index :: IO String -> String

then we could suddenly do IO actions anywhere by calling, for example:然后我们可以通过调用突然在任何地方执行 IO 操作,例如:

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.它被称为unsafePerformIO并且有非常非常好的理由。 Do not use it unless you're 100% sure of what you are doing!除非您 100% 确定自己在做什么,否则不要使用它!

Well you cannot get rid of the IO monad part of IO String .好吧,您无法摆脱IO StringIO monad 部分。 That means you will have to make your function return IO [(String, [Integer])] .这意味着你必须让你的函数返回IO [(String, [Integer])]

I recommend learning more about monads, but for now you can get away with the liftM function:我建议学习更多关于 monad 的知识,但现在你可以使用liftM函数:

liftM index (readFile "input.txt")

liftM has this signature: liftM有这个签名:

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

It takes a non-monadic function and transforms it into a monadic function.它接受一个非一元函数并将其转换为一元函数。

fmap index $ readFile "input.txt"

or或者

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

You may want to look into monad and functors你可能想研究 monad 和 functors

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM