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

thenこの種のシナリオでは、またはで複数の 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

これの標準的な説明は、2つの既存の値から新しいモナディック値を形成したいということです。putStrのタイプを見てみましょう。

IO ()

これは、実行されると、ユニットタイプの(唯一の)値を「返す」ブラックボックスであることを意味します。モナディック計算の背後にある重要なアイデアは、>>=2つのモナディック式をまとめて、一方の結果を次の式(より正確には、次の式を作成する関数)にフィードするコンビネータがあることです。重要な点の1つは、IOライブラリがこのコンビネータを提供することです。つまり、

  • [この場合のIO]は、たとえば最初の値が例外をスローした場合に、2番目のモナディック値をスキップする可能性があります。
  • 開いているファイルハンドルなどを含む状態IOの場合、他のデータを渡すことができます。RealWorld
  • 最も外側の(「最後の」)項が最初に展開されるほとんどのラムダ式の評価とは異なり、最初の評価が最初に評価されることを「保証」できます。これは、最初の印刷で世界を最初に変える必要がある印刷にとって重要です。

あなたの場合、このように使用してください、

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 構文なしで示したかったのです。ここでは do 構文を使用しています。

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 に答える