2017-02-26 2 views
0

getLine関数を呼び出します。IO a - > aから関数を書く?

それは私がこのIO値から文字列を抽出するにはどうすればよいタイプ

getLine :: IO String 

を持っています。より一般的には、どのように変換するのですか?これに

IO a 

a 

これが不可能な場合。なぜ私はこれをすることができないのですか? Haskellで

+7

これを行うことができれば、最初にIOタイプを持つことに意味がないためです。 – sepp2k

+0

重複してしまう:[* HaskellでIO Stringを解析するには?*](http://stackoverflow.com/q/11229854/2751851)重複ターゲット)。 – duplode

答えて

9

、あなたがIOに「閉じ込められた」されている値で作業したい場合、あなたはIO外の値を取ることはありません。代わりに、実行する操作をIOに入れます。

たとえば、Preludeのlength関数を使用して、getLine :: IO Stringが生成する文字の数を確認したいとします。

fmap :: (a -> b) -> IO a -> IO b 

それはIO中に閉じ込められていない「純粋な」値で動作機能を取り、あなたの機能を提供します:

そこには、ヘルパー関数は、型を持っていたときに、特殊なIOに、fmapと呼ばれる存在しますIOにトラップされた値で動作します。これは、コード

fmap length getLine :: IO Int 

は、コンソールから行を読み込みIOアクションを表していることを意味して、あなたにその長さを与えます。

<$>は、事物を簡単にすることができるfmapのインフィックスシノニムです。これは、上記のコードと同等です:今

length <$> getLine 

、あなたがIO -trapped値を返しますIO -trapped値自体で実行したい時々操作。簡単な例:あなたが読み込んだ文字列をputStrLn :: String -> IO()を使って書き戻すことをやめましょう。

この場合、fmapでは不十分です。 IOに特化した場合は、IO a -> (a -> IO b) -> IO bとなる(>>=)演算子を使用する必要があります。うちの場合:

getLine >>= putStrLn :: IO() 

がチェーンにIOアクションを(>>=)を使用することは不可欠で、シーケンシャルな風味を持っています。より自然な方法でこのような一連の動作を記述するのに役立ちます"do-notation"と呼ばれるシンタックスシュガーのようなものがあります:ここ<-が行うが提供する事業者が、シンタックスシュガーの一部ではないことを

do line <- getLine 
    putStrLn line 

お知らせ表記

+0

このよくある質問の簡単な説明「代わりに、実行したい操作をIOに入れます!」 – luqui

1

Cを知っている場合は、「文字列をgetsから取得するにはどうすればよいですか? IO Stringは入手困難な文字列ではなく、ネットワークや標準入力からの文字列のような読み込みを返す手続きです。 文字列を取得する手順を実行します。あなたが望むしかし、値を使用し、その後String値を得ることがgetLine操作を実行して上記で

main = do 
    someString <- getLine 
    -- someString :: String 
    print someString 

:順番にIOアクションを実行するための

一般的な方法は、do表記です。

2

doブロック内にいる場合、<-をIOから値を取得すると(非公式に/不正確に)考えることができます。例えば

は、以下の機能がgetLineから行を取り、単なる文字列

main = do 
    line <- getLine 
    putStrLn (wrap line) 

wrap :: String -> String 
wrap line = "'" ++ line ++ "'" 

あなたはwrapとしてこれをコンパイルした場合は、コマンドラインの実行にかかり、純粋な関数に渡し

echo "Hello" | wrap 

あなたは見るべき

'Hello' 
0

「一般的に」、このタイプの関数が必要な理由は不明です。この場合、すべての違いが生じます。

可能であることを完全に記しておく必要があります。実際にはunsafePerformIOと呼ばれるタイプライブラリIO a -> aの機能がベースライブラリに存在します。

しかし、理由のためにunsafe部分があります。その使用法が正当とみなされる状況はほとんどありません。それは非常に慎重に使用されるエスケープハッチです - ほとんどの時間あなたは自分自身を出す代わりにモンスターを許可します。

通常、IO aからaに移動できないのはなぜですか?まあ、少なくとも純粋ではない一見純粋な機能を持つことによってルールを破ることができます。これを行うことが一般的なプラクティスであった場合は、型シグネチャとコンパイラによって検証されたすべての作業が意味をなさないでしょう。すべての正しさの保証は窓から出るでしょう。

これは(通常)不可能なので、ハスケルは、部分的に面白いです。

あなたのgetLineの問題にどう対処するかについては、他の回答を参照してください。

関連する問題