Haskell IO(字符串)和字符串
我想编写函数并将结果放入字符串。
我想要函数:
read' :: FilePath -> String
我使用:
:t readFile
readFile :: FilePath -> IO String
我制作:
read' :: IO ()
read' = do
str <- readFile "/home/shk/workspace/src/test.txt"
putStrLn str
我想问 str 是不是字符串?
我们知道:
:t putStrLn
putStrLn :: String -> IO ()
那为什么我不能:
read' :: String
read' = do
str <- readFile "/home/shk/workspace/lxmpp/src/test.txt"
str
我收到错误:
Couldn't match expected type `[t0]' with actual type `IO String'
In the return type of a call of `readFile'
In a stmt of a 'do' expression:
str <- readFile "/home/shk/workspace/lxmpp/src/test.txt"
In the expression:
do { str <- readFile "/home/shk/workspace/src/test.txt";
str }
谢谢。
I want to write functions and put result to string.
I want function:
read' :: FilePath -> String
I use:
:t readFile
readFile :: FilePath -> IO String
I make:
read' :: IO ()
read' = do
str <- readFile "/home/shk/workspace/src/test.txt"
putStrLn str
I want to ask str is string or not?
We know that:
:t putStrLn
putStrLn :: String -> IO ()
Then why i can't:
read' :: String
read' = do
str <- readFile "/home/shk/workspace/lxmpp/src/test.txt"
str
I get error that:
Couldn't match expected type `[t0]' with actual type `IO String'
In the return type of a call of `readFile'
In a stmt of a 'do' expression:
str <- readFile "/home/shk/workspace/lxmpp/src/test.txt"
In the expression:
do { str <- readFile "/home/shk/workspace/src/test.txt";
str }
Thank you.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
只是为了多争论一点,虽然其他答案完全正确,但我想强调一点:
IO String
类型的东西不仅仅是类型系统不允许您获得的字符串直接在。这是一种执行 I/O 来为您获取字符串的计算。将readFile
应用于文件路径不会返回String
值,就像将牛排放在绞肉机旁边会神奇地将它们变成汉堡一样。当您有这样的代码时:
这并不意味着您“从
getStr
中取出字符串两次”。这意味着您要执行两次计算,并且很容易在两次之间得到不同的结果。Just to quibble a bit more, while the other answers are perfectly correct, I want to emphasize something: Something with the type
IO String
isn't just a string that the type system won't let you get at directly. It's a computation that performs I/O to get a string for you. ApplyingreadFile
to a file path doesn't return aString
value any more than putting a steak next to a meat grinder magically turns them into a hamburger.When you have some code like this:
That doesn't mean you're "taking the string out of
getStr
twice". It means you're performing the computation twice and can easily get different results between the two.我认为还没有人回答这个非常重要的问题:
我会尽力的。
变量
str
的类型是String
,是的。然而,这个变量的范围是非常有限的。我认为对 do 符号进行脱糖处理对于理解是必要的:
我认为在这里可以更清楚为什么
str
不够好。它是您传递给>>=
的函数的参数。它的值仅在有人调用您的函数时才可用,而这种情况仅在执行包含它的 IO 操作时发生。另外,
read'::IO ()
的类型并不是由putStrLn str
决定的,而是由运算符>
> 的返回类型决定。 >=
。看一下它(专门针对IO
monad):您可以看到结果始终是一个
IO b
操作,因此尝试更改任何参数都不会帮助。如果您想了解为什么类型是这样的,您可以阅读一些 monad 教程。其背后的直觉是:不执行操作就无法执行操作。
在问题的实际方面,使用某个操作返回的值,而不是尝试使用 (extractValue inputAction) ,这没有意义,因为
extractValue
不可能,如果您的use
确实涉及 I/O,请尝试inputAction >>= use
,如果不涉及 I/O,请尝试fmap use inputAction
。I think no one has answered this, very important question, yet:
I will try to.
The type of the variable
str
isString
, yes.However, the scope of this variable is very limited. I think desugaring the do-notation is necessary for understanding:
I think here it becomes more clear why
str
is not good enough. It is an argument of the function you pass to>>=
. Its value only becomes available when someone calls your function, which happens only when theIO
action containing it is being executed.Also, the type of
read' :: IO ()
is determined not so much by theputStrLn str
, but rather by the return type of the operator>>=
. Have a look at it (specialized to theIO
monad):You can see that the result is always an
IO b
action, so trying to change any of arguments won't help.You can read some monad tutorial if you want to understand why the type is the way it is. The intuition behind it is: you can't perform an action without performing an action.
And on the practical side of the question, to use the value returned by some action, instead of trying to do
use (extractValue inputAction)
, which does not make sense becauseextractValue
is not possible, tryinputAction >>= use
if youruse
does involve I/O, orfmap use inputAction
if it does not.如果您希望它返回
str
而不是()
,则应在read'
中使用return str
。您无法从read'
类型中剥离IO
,因为它不是纯函数。为了更好地掌握 Haskell 中输入/输出的工作原理,我建议您阅读教程。You should use
return str
inread'
if you want it to returnstr
instead of()
. You can't stripIO
from the type ofread'
, since it's not a pure function. To get a better grip on how input/output in Haskell works I recommend you to read a tutorial.更详细的原因是:它允许杂质。
绝对不能在纯操作期间执行 IO,否则会完全破坏引用透明性。从技术上讲,您可以使用
unsafePerformIO
,但在这种情况下它会破坏引用透明度 - 仅当您可以保证结果始终相同时才应该使用它。As a more detailed reason why: It allows impurity.
You absolutely can not perform IO during a pure operation, or it would completely break referential transparency. Technically you can use
unsafePerformIO
but it would break referential transparency in this case - you should only use that if you can guarantee that the result is always the same.