21

私は次の機能を持っています:

get :: Chars -> IO Chars
get cs = do
    char <- getChar
    let (dats, idx) = (curData cs, curIndex cs)
    let (x,y:xs) = splitAt idx dats
    let replacement = x ++ (ord char) : xs
    return $ Chars replacement idx

アクションではなくCharsそこから価値を引き出したいのです。私はこれをどのように行うか、あるいはそれが可能であるかどうかさえわかりません。IO

Charsタイプは基本的に単なるコンテナです。

data Chars = Chars {
               curData  :: [Int],
               curIndex :: Int
               -- etc.
             }

Chars詳細はそれほど重要ではありません。この関数がの代わりにを返す方法があるかどうかを知りたいだけですIO Chars

そうでない場合、これを引数として?を取る関数に渡すにはどうすればよいCharsですか?私はHaskellI/ Oに少し慣れていませんがChars、引数として取るすべての関数を代わりに引数として取りIO Chars、それらを抽出して再パッケージ化する必要はないと思います。不要のようです。

ありがとう!

4

2 に答える 2

27

参照の透過性に違反するため、できません。

Haskell の IO は、環境/ユーザーとの相互作用に応じて結果と効果が異なる可能性があるアクションと、同じ入力パラメーターでそれらを呼び出しても結果が変わらない純粋な関数を正確に区別するために、このように作成されます。

入力を受け取る純粋な関数に結果を渡すにはChars、IO アクションを別の IO アクションに呼び出し、<-演算子を使用して結果を変数にバインドし、それを純粋な関数に渡す必要があります。擬似コードの例:

myPureFunction :: Chars -> ...

otherAction :: Chars -> IO ()
otherAction cs = do
  myChars <- get cs
  let pureResult = myPureFunction myChars
  ...

Haskell で IO を初めて使用する場合は、Haskell を学んで大成功を収める の入力と出力の章をご覧になることをお勧めします。そして実世界のハスケル

実際には、IOアクションから純粋な値を単純に取得する方法がありますが、環境と対話しているため、あなたの場合はそうすべきではありません:安全でない方法は、あなたが参照透過性に違反していません。

于 2012-07-13T08:50:35.687 に答える
11

それは不可能です (嘘をつきます。ごまかすには非常に危険な方法があります)。

要点は、I/O が実行される場合、プログラムの動作と結果は、使用される関数への明示的な引数だけに依存しない可能性があるため、それを使用して型で宣言する必要があるということIO somethingです。

IO aアクションの結果を純粋関数で使用するには、結果をmain(またはから呼び出されるものmain) にバインドしてから、純粋関数を適用し、結果を , にバインドしますlet

cs ::Chars
cs = undefined

main = do
  chars <- get cs
  let result = pureFunction chars
  print result

または、適用する関数にcharsタイプがある場合Chars -> IO b

main = do
    chars <- get cs
    doSomething chars
于 2012-07-13T08:54:03.520 に答える