Haskell IO(String)和String

0xA*_*xAX 7 io haskell input

我想写函数并将结果放到字符串中.

我想要的功能:

read' :: FilePath -> String
Run Code Online (Sandbox Code Playgroud)

我用:

:t readFile
readFile :: FilePath -> IO String
Run Code Online (Sandbox Code Playgroud)

我做:

read' :: IO ()
read' = do
     str <- readFile "/home/shk/workspace/src/test.txt" 
     putStrLn str
Run Code Online (Sandbox Code Playgroud)

我想问str是不是字符串?

我们知道:

:t putStrLn
putStrLn :: String -> IO ()
Run Code Online (Sandbox Code Playgroud)

那我为什么不能:

read' :: String
read' = do
     str <- readFile "/home/shk/workspace/lxmpp/src/test.txt" 
     str
Run Code Online (Sandbox Code Playgroud)

我得到错误:

 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 }
Run Code Online (Sandbox Code Playgroud)

谢谢.

C. *_*ann 10

只是为了狡辩多一点,而其他答案是完全正确的,我想强调一下:类型的东西IO String不仅仅是类型系统不会让你直接得到的字符串.这是一个执行I/O以获取字符串的计算.应用于readFile文件路径不会返回String任何值,只需将绞肉机放在绞肉机旁边就会神奇地将它们变成汉堡包.

当你有这样的代码时:

foo = do let getStr = readFile "input.txt"
         s1 <- getStr
         s2 <- getStr
         -- etc.
Run Code Online (Sandbox Code Playgroud)

这并不意味着你"把弦带走getStr两次".这意味着您正在执行两次计算,并且可以轻松地在两者之间获得不同的结果.


Rot*_*sor 6

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

我想问str是不是字符串?

我会试着去.

变量的类型strString,是的.但是,此变量的范围非常有限.我认为贬低这种记法对于理解是必要的:

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

我认为这里更清楚为什么str不够好.它是您传递给函数的参数>>=.只有在有人调用您的函数时才会显示其值,该函数仅在IO执行包含它的操作时才会发生.

而且,类型的read' :: IO ()确定不是由putStrLn str操作员的返回类型决定的,而是由操作员的返回类型决定的>>=.看看它(专门为IOmonad):

(>>=) :: IO a -> (a -> IO b) -> IO b
Run Code Online (Sandbox Code Playgroud)

您可以看到结果总是一个IO b动作,因此尝试更改任何参数都无济于事.

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

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