IO関数内で純関数を使用するにはどうすればよいですか? : -/Haskell - IO関数内で純関数を使用するにはどうすればよいですか?
例:私はファイル(IO関数)を読んでいて、参照用の透明性を持つ純粋な関数を使用して、そのコンテキスト(文字列)を解析したいと考えています。
純粋な関数とIO関数のような世界は分かれているようです。どうすればそれらを橋渡しできますか?
IO関数内で純関数を使用するにはどうすればよいですか? : -/Haskell - IO関数内で純関数を使用するにはどうすればよいですか?
例:私はファイル(IO関数)を読んでいて、参照用の透明性を持つ純粋な関数を使用して、そのコンテキスト(文字列)を解析したいと考えています。
純粋な関数とIO関数のような世界は分かれているようです。どうすればそれらを橋渡しできますか?
アレックス・ホースマンが私を助けました。彼は言った:
は "おそらく、私は誤解だけど、それは非常に単純 聞こえるん{X < - ioFunc;リターン(pureFuncのX)}?" を
そして、私は私の問題解決:
import System.IO
import Data.List
getFirstPart line Nothing = line
getFirstPart line (Just index) = fst $ splitAt index line
eliminateComment line =
getFirstPart line $ elemIndex ';' line
eliminateCarriageReturn line =
getFirstPart line $ elemIndex '\r' line
eliminateEntersAndComments :: String -> String
eliminateEntersAndComments text =
concat $ map mapFunction $ lines text
where
mapFunction = (++ " ") . eliminateCarriageReturn . eliminateComment
main = do {
contents <- readFile "../DWR-operators.txt";
return (eliminateEntersAndComments contents)
}
を
また、liftM関数をControl.Monadから考えることもできます。
fmap :: (Functor f) => (a -> b) -> f a -> f b
IO
:
少し例あなたは
$ import Control.Monad -- to emerge liftM
$ import Data.Char -- to emerge toUpper
$ :t map to Upper -- A pure function
map toUpper :: [Char] -> [Char]
$ :t liftM
liftM :: Monad m => (a1 -> r) -> m a1 -> m r
$ liftM (map toUpper) getLine
最も簡単な方法は、次の型を持っているfmap
を、使用することです(あなたはIOモナドの下にあるようGHCiの中にそれを実行する)を支援するためにFunctor
を実装しています。つまり、IO
をf
に置き換えて上記のタイプを特殊化することができます。
fmap :: (a -> b) -> IO a -> IO b
つまり、a
をb
に変換する関数を使用し、これを使用してIO
アクションの結果を変更します。例:
getLine :: IO String
>>> getLine
Test<Enter>
Test
>>> fmap (map toUpper) getLine
Test<Enter>
TEST
何が起こったのですか?まあ、map toUpper
は型を持つ:
map toUpper :: String -> String
それは引数としてString
をとり、結果としてString
を返します。具体的には、文字列全体を大文字にします。
さて、fmap (map toUpper)
の種類を見てみましょう:
fmap (map toUpper) :: IO String -> IO String
我々はIO
値で動作するように私達の機能をアップグレードしました。 IO
アクションの結果を変換して、大文字のストリングを返します。それは、すべてのモナドには、次の性質を持っていることが判明し
getUpperCase :: IO String
getUpperCase = do
str <- getLine
return (map toUpper str)
>>> getUpperCase
Test<Enter>
TEST
:つまり
fmap f m = do
x <- m
return (f x)
、いずれかのタイプがMonad
を実装している場合、
我々はまたに、do
表記を使ってこれを実装することができます上記の定義を使用して、常にFunctor
を実装できるはずです。実際には、我々は常にfmap
のデフォルトの実装としてliftM
を使用することができます。
liftM :: (Monad m) => (a -> b) -> m a -> m b
liftM f m = do
x <- m
return (f x)
liftM
はファンクタのように一般的ではありませんモナドに特化した以外、fmap
と同じです。あなたは、あなたができる使用のいずれかIO
アクションの結果を変換したい場合は
ので:
fmap
、liftM
、またはdo
表記それは本当に最高ですあなたが好きなものをあなたに教えてください。私は個人的にfmap
をお勧めします。
IOアクションから*純粋な関数*を呼び出す方法ではなく、IOアクションの結果を抽出する方法を説明していませんか? –
次のように実際の答えは次のとおりです。
main = do
val <- return (purefunc)
return
ヴァルに割り当てることができないような適切なモナドでそれをラップします。
チュートリアルを読んだことがありますか?あなたの質問には、haskellのIOの紹介があります。ソリューションは、IO Monadを作成することです。 – epsilonhalbe
ありがとうございます。私はこの問題を解決しました。以下のようになります。 –