1

IO文字列から文字列へのそのような違いはありますか

IO からいくつかの文字列値を取得したいと考えています。

誰でもこの問題について教えてください。私は無知です

4

2 に答える 2

6

問題は、プログラムが実行されたときに、アクションの結果として得られるString値をどうしたいかです。IO Stringあなたはすでに弦を手にしているかのように書いていますが、そうではありません。

または: 文字列を定義または分離したかのように書きますが、そうではありません。ここまでで、文字列を返すアクションを定義または分離しました。そのアクションを実行する個々のケースでは、異なる文字列が返されます。

おそらく、より複雑なアクション (何かの型) を定義しようとしているのでしょIO BlahIO ()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 ()

したがって、そのようなもののペアの最も些細な例を挙げるために、 と を考えてみましょgetLineputStrLn

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 のベルが鳴るのが聞こえます。これはかなり不自由なオーディオ プログラムですが、これで終わりです。 ghciUnix のベルを鳴らすアクションを実行してい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
于 2010-03-18T16:13:57.700 に答える
4

IO String は IO-Monad の String です。IO-Monad の関数が IO 文字列を返す場合、次のようにして文字列を取得します。

do str <- ioFunc

関数が IO アクセスを必要とし、IO 型を返さなければならない場合、その関数は IO-Monad にあります。

于 2010-03-18T08:36:38.523 に答える