Haskell IO(字符串)和字符串

Haskell IO(字符串)和字符串,haskell,input,io,Haskell,Input,Io,我想编写函数并将结果放入字符串 我想要功能: read' :: FilePath -> String 我使用: :t readFile readFile :: FilePath -> IO String 我提出: read' :: IO () read' = do str <- readFile "/home/shk/workspace/src/test.txt" putStrLn str 那为什么我不能: read' :: String read'

我想编写函数并将结果放入字符串

我想要功能:

read' :: FilePath -> String
我使用:

:t readFile
readFile :: FilePath -> IO String
我提出:

read' :: IO ()
read' = do
     str <- readFile "/home/shk/workspace/src/test.txt" 
     putStrLn str
那为什么我不能:

read' :: String
read' = do
     str <- readFile "/home/shk/workspace/lxmpp/src/test.txt" 
     str
read'::字符串
读“=do

str如果希望它返回
str
,而不是
()
,则应在
read'
中使用
return str
。您不能从
read'
类型中删除
IO
,因为它不是一个纯函数。为了更好地掌握Haskell中输入/输出的工作原理,我推荐您。

更详细的原因是:它允许杂质


您绝对不能在纯操作期间执行IO,否则会完全破坏引用透明性。从技术上讲,您可以使用
unsafePerformIO
,但在这种情况下,它会破坏引用的透明度-只有在能够保证结果始终相同的情况下,您才应该使用它。

只是为了再多吹毛求疵一点,而其他答案是完全正确的,我想强调一点:类型为
IO String
的内容不仅仅是类型系统无法直接获取的字符串。它是一种执行I/O以获取字符串的计算。将
readFile
应用于文件路径不会返回
String
值,就像将牛排放在绞肉机旁边会神奇地将它们变成汉堡包一样

当您有如下代码时:

foo = do let getStr = readFile "input.txt"
         s1 <- getStr
         s2 <- getStr
         -- etc.
foo=do让getStr=readFile“input.txt”

s1我认为还没有人回答这个非常重要的问题:

我想问str是不是字符串

我会尽力的

变量
str
的类型为
String
,是。 然而,这个变量的范围非常有限。我认为去除do符号对于理解以下内容是必要的:

read' = readFile "/home/shk/workspace/src/test.txt" >>= (\str -> putStrLn str)
我想在这里,我们可以更清楚地看到为什么
str
不够好。它是传递给
>=
的函数的参数。它的值只有在有人调用您的函数时才可用,这只有在执行包含它的
IO
操作时才会发生

另外,
read':IO()
的类型不是由
putStrLn str
决定的,而是由操作符
>=
的返回类型决定的。看看它(专门用于
IO
monad):

您可以看到,结果总是一个
iob
操作,因此尝试更改任何参数都没有帮助

如果你想了解为什么是这样的类型,你可以阅读一些monad教程。它背后的直觉是:不执行动作就不能执行动作


在问题的实际方面,使用某个操作返回的值,而不是尝试执行
use(extractValue inputation)
,这是没有意义的,因为
extractValue
是不可能的,如果
use
确实涉及I/O,请尝试使用
inputation>=use
,或者
fmap使用inputAction
,如果没有。

do符号中的readFile表示您在IO单子中,并且IO单子无法转义@is7s,除非您使用
unsafePerformIO
!不安全的第一条规则是你不能告诉任何人关于不安全的事@托马斯,呃,哦,就像现实世界中的哈斯凯尔打破了那样rule@Thomas除非他理解广义的预组对称性,否则这是正确的,请注意,与
绑定没有任何意义,是否保证结果足够相同以声称纯度?我的意思是,
unsafePerformIO(putStrLn“hello!”)
能被称为纯吗?@Rotsor:别忘了它也必须是线程安全的。手动保证纯度是困难的@camccann我不知道如何解释你的评论。你是在扩展用户定义的一元纯度的概念,还是在暗示实现它的实际困难?如果不扩展,它可以通过,比如说,
safePerformIO=unsafePerformIO::IO()->()
,来实现,对吗?这是不好的。。。还是不?@罗特:啊,对不起,不清楚。我用“不,这还不够”来回答你的问题,并添加了一个额外的要求,即即使它使用的是
ST
-样式包含杂质,它也必须独立于可能的并发资源访问。在<>代码> unSimePrimeIO/COD>存在的情况下确保纯度确实是非常非常困难的。但是,是的,这通常是一个信号,表明它并不纯粹。基本上,你不应该在意是否使用了之前计算的值。神奇汉堡的好处是你可以吃它们而不用担心副作用!
foo = do let getStr = readFile "input.txt"
         s1 <- getStr
         s2 <- getStr
         -- etc.
read' = readFile "/home/shk/workspace/src/test.txt" >>= (\str -> putStrLn str)
(>>=) :: IO a -> (a -> IO b) -> IO b