获取并在 Haskell 中放入一个字符串会抛出错误

Get and put a string in Haskell throws error

我找到了以下 Haskell 代码,但我很困惑:

main = putStrLn "Enter 1st String:"  
  >> getLine
  >>= \a -> read a
  1. 两个"greater than"符号(>>)是什么意思?新声明?

  2. 两个"greater than"符号后跟一个等号(>>=)是什么意思?

此 Haskell 代码抛出以下错误:

a.hs:3:13:
No instance for (Read (IO t0)) arising from a use of ‘read’
In the expression: read a
In the second argument of ‘(>>=)’, namely ‘\ a -> read a’
In the expression:
  putStrLn "Enter 1st String:" >> getLine >>= \ a -> read a

1) does two greater than symbols mean a new statement?

在这种情况下,是的。在 IO monad 中,>> 大致等同于许多命令式编程语言中的 ;

2) what does two greater than symbols followed by equal sign mean?

x >>= yx >> y 类似,只是它采用 x 的结果并应用于 y,后者必须是一个函数。简而言之,getLine >>= \a -> action 表示“读取一行,将该值绑定到变量 a,以及 运行 action(可以依赖于 a)。

我推荐一个 monad 教程来完全理解这些。您可以从一般教程开始,例如 LYAH.

您的代码更常用 do 表示法:

main = do
  putStrLn "Enter 1st String:"  
  a <- getLine
  read a

最后一行没有意义:read returns 一个值但不做任何 I/O,因此我们不能将其链接到 [=39= 的序列] 动作。这会触发编译器错误。如果你知道一些命令式编程,想想伪代码

print("some message");
a = inputLine();
toInteger(a);

最后一行毫无意义:它将字符串转换为整数...然后不以任何方式使用结果。

关于您的第二个问题:您的 main 不是有效的单子表达式。当专用于 IO monad 时,bindthen 运算符的类型为

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

如果您尝试对齐 main 表达式的类型,您会很快发现问题所在:

putStrLn "Enter 1st String:"  >>  getLine   >>=  \a -> read a

{           IO ()          }    {IO String}      {actual: Read t => String -> t   }

{                  IO String              }      {expected:         String -> IO t}         ???         }

>>= 的第二个参数预期的类型是 String -> IO t,但 read 不是 return 一个 IO 值。