为什么 `putStrLn getLine` 不起作用?

7

我是Haskell的新手。我的Haskell脚本使用GHCi

Prelude> let a = putStrLn getLine

假如出现了这样的错误。

<interactive>:1:17:
    Couldn't match expected type `String'
           against inferred type `IO String'
    In the first argument of `putStrLn', namely `getLine'
    In the expression: putStrLn getLine
    In the definition of `a': a = putStrLn getLine
Prelude> 

为什么它不能正常工作,我该如何打印从stdin输入的内容?

1个回答

15
putStrLn :: String -> IO ()
getLine :: IO String

类型不匹配。 getLine 是一个 IO 动作,而 putStrLn 接受一个普通字符串。

你需要将行绑定在 IO 单子内,以便将其传递给 putStrLn。以下是等效的示例:

a = do line <- getLine
       putStrLn line

a = getLine >>= \line -> putStrLn line

a = getLine >>= putStrLn

2
你在IO单子m a中有一个值,以及一个返回其值在IO单子a -> m b中的函数。你想要最终得到一个IO操作m b。总之,这是m a -> (a -> m b) -> m b停一下,Hoogle时间。 >>=是其中的第一个结果。 :) - Dan Burton
很遗憾,我们需要的精确实例化IO String -> (String -> IO ()) -> IO ()没有结果。 - luqui
Eonil,如果你想更接近于putStrLn getLine的意图,可以使用类似的反向绑定:putStrLn =<< getLine。这是fmap后跟着join,所以我们可以写成join (putStrLn <$> getLine)。但我希望有比(=<<)更优雅的方式。 - applicative

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接