2011-12-19 17 views
1

私はハスケルといくつかの自己学習をしようとしています。ハスケル型チェック

関数loadDataはファイルからデータを読み込み、整数パラメータに基づいてマップを生成するために何らかの処理を行います。私はそのような2つのマップを作成し、それにコサイン類似度メトリックを適用する必要があります。まず、2つのマップの交差を見つけることを試みています。しかし、私はタイプエラー()に遭遇するloadDataの出力をMap.intersectionにどのように送ることができますか?機能アプリケーター$が必要ですか?

loadData :: Int -> FilePath -> IO (Map.Map [Char] Double) 

Map.intersection :: Ord k => Map.Map k a -> Map.Map k b -> Map.Map k a 
+0

IOの処理方法はまだ分かりますか? – fuz

+0

'loadData'の出力を' Map.intersection'にどのように供給しようとしていますか?あなたのコードを私たちに教えてください。 – dave4420

+0

私はMap.intersectionをやってみました。<$>(loadData1 "firstFile")<$>(loadData1 "secondFile") – atlantis

答えて

3

このような何か:この結果はIO (Map.Map String Double)型を持つこと

import Control.Applicative 

Map.intersection <$> loadData param filename1 <*> loadData param filename2 

注意を。

+0

私はおそらくIOのメカニズムを正しく取得していません。ですから、一度IOを返すloadDataのreadFileを行うと、モナドのコンテキストで永遠に動作させる必要がありますか?または、単に「抽出」して使用する方法はありますか? – atlantis

+2

値を '抽出'し、 '<$>'、 '<*>'、 '>> ='などの関数を使用して値を使用することができます。しかし、あなたはいつも「IO」の何かで終わります。 –

+4

あなたがモナドのコンテキストで永遠に動作していると言うのはもう少し正しいでしょう。また、 '<$>'、 '<*>'、そして '>> = 'のコンビネータは、非IO関数を対処する方法IOのビット。 –

4

あなたの質問にFUZxxlがコメントしたように、私はあなたがHaskell I/Oをどの程度調べているか質問します。これは、言語を利用するために乗り越える大きな初期のハードルの1つであり、より簡単なタスクから始めたいと思うようです。

さらに、あなたの質問にもっと答えるために、ここでは2つの方法があります。まず、基本1、あなたは他のものが意味を作る前に、まず理解する必要がある1:

processData :: Int -> FilePath -> Int -> FilePath -> IO (Map.Map [Char] Double) 
processData int1 path1 int2 path2 = 
    do map1 <- loadData int1 path1 
     map2 <- loadData int2 path2 
     return (Map.intersection map1 map2) 

関数に上記のようなパターンを抽象伴い、より高度な答えがあります。これを行うより基本的な方法は、Control.MonadモジュールのliftM2関数を使用することです。私はちょうどそれは、上記のコードに関連していますどのようにそれを明らかにするためにliftM2の実装例をあげる:

processData :: Int -> FilePath -> Int -> FilePath -> IO (Map.Map [Char] Double) 
processData int1 path1 int2 path2 = 
    liftM2 Map.intersection (loadData int1 path1) (loadData int2 path2) 

dave4420の答えは次のとおりです。liftM2

liftM2 :: Monad m => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r 
liftM2 f mx my = do x <- mx 
        y <- my 
        return (f x y) 

、我々はprocessDataをこのように書き換えることができますもう少し進んだ。つまり、Control.Applicativeには、liftM2と同じことを行うことができる2つの演算子(<$><*>)がありますが、liftM2が最初の引数として取る関数の任意の数の引数があります。