IO文字列から文字列へのそのような違いはありますか
IO からいくつかの文字列値を取得したいと考えています。
誰でもこの問題について教えてください。私は無知です
問題は、プログラムが実行されたときに、アクションの結果として得られるString
値をどうしたいかです。IO String
あなたはすでに弦を手にしているかのように書いていますが、そうではありません。
または: 文字列を定義または分離したかのように書きますが、そうではありません。ここまでで、文字列を返すアクションを定義または分離しました。そのアクションを実行する個々のケースでは、異なる文字列が返されます。
おそらく、より複雑なアクション (何かの型) を定義しようとしているのでしょIO Blah
うIO ()
。String
より複雑なアクションでは、タイプのアクション (これまでに定義したアクション) を実行することによって値に到達するIO String
と、複雑なアクションのエグゼキュータが、何に依存するかを実行し続けるという考えです。その値は。これは、タイプの関数によって表されるものですString -> IO Blah
-- たぶんString -> IO ()
もちろん、そのような関数はIO String
値 (つまり、文字列を返すアクション) を引数として取りませんが、String
値を引数として取ります。直接参加することはできません。
文字列を返すアクション (値) と 'String -> IO Blah' 関数から何か新しいもの (何かを返すアクション)IO String
を取得するに は、 function を介してそれらを結合します>>=
。このケースに特化し>>=
たタイプIO String -> (String -> IO Blah) -> IO Blah
があります -- それはそうかもしれませんIO String -> (String -> IO ()) -> IO ()
したがって、そのようなもののペアの最も些細な例を挙げるために、 と を考えてみましょgetLine
うputStrLn
。
getLine
は、入力されたばかりの文字列を見つけるアクションです。タイプはIO String
です。
putStrLn
画面に値を出力してString
から、左マージンに戻ると言うかもしれません。String
しかし、それは表面的なものです: どのような明確なことが行われるかは、値の仕様に依存するため、 type を持ちString -> IO()
ます。つまりputStrLn
、何もしません。これは、文字列を実行可能なものにマップする関数です。 したがって、いつもIO ()
のように、関数記号の後にドメイン タイプ (strings 、String
つまり.putStrLn "Gee whiz"
IO ()
ghci
はその場でそのようなアクションを実行するので、「Gee whiz」のような任意の文字列を書くputStrLn "Gee whiz"
と、すぐに「このアクションを実行」します。つまり、「Gee whiz」を画面に書き込んで左マージンに戻るアクションです。
Prelude> putStrLn "Gee whiz"
Gee whiz
Prelude>
同様に、Unix のベル文字だけを含む 1 文字の文字列は、 or\BEl
で名前を付ける文字列です。引数としてのその文字列の場合、値に対してかなり異なる種類のアクションが聞こえます。我々が得る'\BEl':[]
['\BEL']
"\BEL"
putStrLn
Prelude> putStrLn "\BEL"
Prelude>
ここでは、左マージンに戻る前に Unix のベルが鳴るのが聞こえます。これはかなり不自由なオーディオ プログラムですが、これで終わりです。 ghci
はUnix のベルを鳴らすアクションを実行していputStrLn "\BEL"
ます。このアクションには、 return キーを押す前に単語を付けて名前を付けました。
とにかくgetLine
、型の値であり、IO String
「この文字列値を IO から取得」する必要があります。もちろん、まだ存在していません。ユーザーが何を入力するかによって異なります。しかし、そのような値を取得したときにプログラムが何をするかを考えることができます。のように、文字列からアクションへの関数を指定することで、これを指定できますputStrLn
。したがって、「値を取る」完全なアクションを定義し、砂糖表記でそれらを構成することにより、特定の方法でそれを使用でき>>=
ますdo
。
最も些細なケースは次のようなものですecho
:
echo :: IO ()
echo = getLine >>= putStrLn
または同等に
echo = getLine >>= (\x -> putStrLn x)
またはdo
記法で:
echo = do
the_string_i_want_to_take <- getLine
putStrLn the_string_i_want_to_take
またはそれほどばかげたことではありません:
echo = do
x <- getLine
putStrLn x
もちろん、「文字列を取り」、終了する前にそれをいじりたいと思うでしょう。
reverseEcho :: IO ()
reverseEcho = getLine >>= (\x -> putStrLn (reverse x))
またはよりコンパクトに:
reverseEcho = getLine >>= (putStrLn . reverse)
またはdo
記法で:
reverseEcho = do
the_string_i_want_to_take <- getLine
putStrLn (reverse the_string_i_want_to_take)
またはそれほどばかげたことではありません:
reverseEcho = do
x <- getLine
putStrLn (reverse x)
「文字列を逆にする」ことを、文字列の取得と印刷の間に行われる何かと考えたい場合は、次のように書くことができます。
reverseEcho = do
the_string_i_want_to_take <- getLine
the_string_after_i_have_processed_it <- return (reverse the_string_i_want_to_take)
putStrLn (the_string_after_i_have_processed_it)
また
reverseEcho = do
x <- getLine
y <- return x
putStrLn y
または同等に
reverseEcho = (getLine >>= (return . reverse)) >>= putStrLn
.
ここでは、との優先レベル>>=
が適切に最適化されているため、括弧は必要ありません。しかし(getLine >>= (return . reverse))
、「文字列を返すアクション」の別の名前でありIO String
、文字列自体ではない の値です。String -> Whatever
関数を直接適用して を取得することはできませんが、を介してWhatever
文字列からアクション>>=
への関数と組み合わせることができます。
同様に
reverseFileAA :: IO ()
reverseFileAA = readFile "AA.txt" >>= writeFile "reversedAA.txt" . reverse
で見つかった文字列を逆にした「reversedAA.txt」という名前のファイルを書き込むアクションであり、AA.txt
それが何であれ、書き込まれる可能性があります
reverseFileAA = do
old_file_contents <- readFile "AA.txt"
new_file_contents <- return (reverse old_file_contents)
writeFile "reversedAA.txt" old_file_contents
IO String は IO-Monad の String です。IO-Monad の関数が IO 文字列を返す場合、次のようにして文字列を取得します。
do str <- ioFunc
関数が IO アクセスを必要とし、IO 型を返さなければならない場合、その関数は IO-Monad にあります。