繁体   English   中英

Haskell IO(字符串)和字符串

[英]Haskell IO (String) and String

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

我想要 function:

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 }

谢谢你。

再狡辩一点,虽然其他答案完全正确,但我想强调一点: IO String类型的东西不仅仅是类型系统不会让你直接得到的字符串。 它是一种执行 I/O 来为您获取字符串的计算。 readFile应用于文件路径不会返回String值,就像将牛排放在绞肉机旁边神奇地将它们变成汉堡包一样。

当你有这样的代码时:

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

这并不意味着您“将字符串从getStr中取出两次”。 这意味着您要执行两次计算,并且可以轻松地在两者之间获得不同的结果。

我认为没有人回答过这个非常重要的问题,但是:

我想问 str 是不是字符串?

我会试着去。

变量str的类型是String ,是的。 但是,这个变量的 scope 是非常有限的。 我认为去除 do-notation 的糖分对于理解是必要的:

read' = readFile "/home/shk/workspace/src/test.txt" >>= (\str -> putStrLn str)

我认为这里更清楚为什么str不够好。 这是您传递给>>=的 function 的参数 它的值只有在有人调用您的 function 时才可用,只有在执行包含它的IO操作时才会发生这种情况。

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

(>>=) :: IO a -> (a -> IO b) -> IO b

您可以看到结果始终是IO b操作,因此尝试更改任何 arguments 都无济于事。

如果您想了解类型为何如此,您可以阅读一些 monad 教程。 其背后的直觉是:不执行动作就无法执行动作。

在问题的实际方面,要使用某些操作返回的值,而不是尝试use (extractValue inputAction) ,这没有意义,因为extractValue是不可能的,尝试inputAction >>= use如果您use则使用涉及 I/O,如果不涉及,则fmap use inputAction

如果您希望它返回str而不是() ,则应该在read'中使用return str 您不能从read'类型中删除IO ,因为它不是纯 function。 为了更好地了解 Haskell 中的输入/输出如何工作,我建议您阅读教程

作为更详细的原因:它允许杂质。

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

暂无
暂无

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

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