2013-02-17 26 views
5

IO関数内で純関数を使用するにはどうすればよいですか? : -/Haskell - IO関数内で純関数を使用するにはどうすればよいですか?

例:私はファイル(IO関数)を読んでいて、参照用の透明性を持つ純粋な関数を使用して、そのコンテキスト(文字列)を解析したいと考えています。

純粋な関数とIO関数のような世界は分かれているようです。どうすればそれらを橋渡しできますか?

+3

チュートリアルを読んだことがありますか?あなたの質問には、haskellのIOの紹介があります。ソリューションは、IO Monadを作成することです。 – epsilonhalbe

+0

ありがとうございます。私はこの問題を解決しました。以下のようになります。 –

答えて

1

アレックス・ホースマンが私を助けました。彼は言った:

は "おそらく、私は誤解だけど、それは非常に単純 聞こえるん{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) 
} 
2

また、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 
8

最も簡単な方法は、次の型を持っているfmapを、使用することです(あなたはIOモナドの下にあるようGHCiの中にそれを実行する)を支援するためにFunctorを実装しています。つまり、IOfに置き換えて上記のタイプを特殊化することができます。

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

つまり、abに変換する関数を使用し、これを使用して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をお勧めします。

+0

IOアクションから*純粋な関数*を呼び出す方法ではなく、IOアクションの結果を抽出する方法を説明していませんか? –

0

次のように実際の答えは次のとおりです。

main = do 
    val <- return (purefunc) 

returnヴァルに割り当てることができないような適切なモナドでそれをラップします。

関連する問題