4
input <- readLn
 if (input == 0)
 then 
  putStr  "0" 
 else if (input ==1)
then 
  putStr  "1" 
else if (input ==2)

then在这种情况下,如何在 a or中使用多个 putStr else if

当我尝试出错时

Type error in application
*** Expression     : putStr "0" putStr "0"
*** Term           : putStr
*** Type           : String -> IO ()
*** Does not match : a -> b -> c -> d
4

3 回答 3

8

使用do- 表示法:

do
  a <- something
  if a 
  then
    do
      cmd1
      cmd2
  else
    do
      cmd3
      cmd4
  cmd5 -- this comes after the 'then' and the 'else'
于 2011-06-08T19:00:29.377 回答
6

对此的规范解释是,您想从两个现有的一元值中形成一个新的一元值。我们来看看 putStr 的类型,

IO ()

这意味着它是一个黑匣子,在执行时将“返回”单元类型的(唯一的)值。一元计算背后的关键思想是你有一个组合>>=器,它将两个一元表达式组合在一起,将一个的结果输入下一个(更准确地说,一个创建下一个的函数)。一个关键点是IO提供了这个组合器,这意味着,

  • 它 [IO 在这种情况下] 可以跳过第二个单子值,例如当第一个抛出异常时。
  • 在包含打开文件句柄IO的状态等情况下,它可以传递其他数据。RealWorld
  • 它可以“确保”第一个首先计算,这与大多数 lambda 表达式计算不同,其中最外层(“最后一个”)项首先展开。这对印刷很重要,因为第一次印刷需要首先改变世界。

在你的情况下,像这样使用它,

putStr "0" >>= (\c -> putStr "0")

当然有捷径

putStr "0" >> putStr "0"

还有 do-notation,正如另一张海报所提到的,它更像是语法糖,

do
    putStr "0"
    putStr "0"
于 2011-06-08T19:19:02.237 回答
5

对于这个人为的示例,您也可以使用一个案例,如下所示:

main = readLn >>= \input -> case input of
    0 ->    putStrLn "0"

    1 ->    putStrLn "0"

    2 ->    putStr   "0" 
         >> putStrLn "0"

    3 ->    putStr   "0"
         >> putStr   "0"
         >> putStrLn "0"

    _ ->    putStrLn "infinite"

使用 do 语法可能更易于阅读,但我想先不使用 do 语法来展示它,只是为了强调 do-syntax 只是语法,实际上并没有做任何特别的事情。这里是do-syntax。

main = do
    input <- readLn
    case input of
        0 -> putStrLn "0"

        1 -> putStrLn "0"

        2 -> do putStr   "0" 
                putStrLn "0"

        3 -> do putStr   "0"
                putStr   "0"
                putStrLn "0"

        _ -> putStrLn "infinite"
于 2011-06-08T19:41:10.247 回答