获取并在 Haskell 中放入一个字符串会抛出错误
Get and put a string in Haskell throws error
我找到了以下 Haskell 代码,但我很困惑:
main = putStrLn "Enter 1st String:"
>> getLine
>>= \a -> read a
两个"greater than"符号(>>
)是什么意思?新声明?
两个"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 >>= y
与 x >> 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 时,bind 和 then 运算符的类型为
(>>=) :: 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
值。
我找到了以下 Haskell 代码,但我很困惑:
main = putStrLn "Enter 1st String:"
>> getLine
>>= \a -> read a
两个"greater than"符号(
>>
)是什么意思?新声明?两个"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 >>= y
与 x >> 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 时,bind 和 then 运算符的类型为
(>>=) :: 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
值。