2017-09-08 16 views
2

私はHaskell(そして一般的なプログラミング)の新機能であり、パラメータとして2つの行列を取る "profileDistance m1 m2"という関数を記述しようとしています。各マトリックスの各要素間の差の合計を計算する必要があります...私はそれを非常によく説明していないかもしれません。代わりにそれを見せてください。Haskell - 各行列の各要素の差の和

行列がの形に​​あります。各行列は次のようなものに見えるかもしれません[[(Char,Int)]]

m1 = [[('A',1),('A',2)], 
     [('B',3),('B',4)], 
     [('C',5),('C',6)]] 

m2 = [[('A',7),('A',8)], 
     [('B',9),('B',10)], 
     [('C',11),('C',12)]] 

は(注:私はこの例では、順番に数字を書いたが、それらはいずれかの内の任意の番号をすることができ。。

result = ((snd m1['A'][0])-(snd m2['A'][0]))+((snd m1['A'][1])-(snd m2['A'][1]))+((snd m1['B'][0])-(snd m2['B'][0]))+((snd m1['B'][1])-(snd m2['B'][1]))+((snd m1['C'][0])-(snd m2['C'][0]))+((snd m1['C'][1])-(snd m2['C'][1])) 
:順序の例に示すように、各行列の各行における文字しかし一致する)

結果()上記の場合には(擬似コード)のようになります

これは、for-loopsを持っていて機能しないどの言語でも簡単に実行できますが、Haskellでこれを行う方法はわかりません。 mapfoldまたはsumのような機能が私をここで助けてくれると感じています(確かに、foldがどのように動作するかは100%確信していません)。私はこれを行う簡単な方法があることを願っています...助けてください。ここで

答えて

6

提案:

solution m1 m2 = sum $ zipWith diffSnd flatM1 flatM2 
    where 
    diffSnd t1 t2 = snd t1 - snd t2 
    flatM1 = concat m1 
    flatM2 = concat m2 

それはビルディング・ブロックを理解することは簡単だように、私はそれを書きました。 基本的な考え方は、zipWithを使用して2つのペアのリストを同時に反復することです。ここでは、そのタイプ:

zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] 

それはタイプa -> b -> caのリスト年代とbのリスト年代に機能を取り、それがc年代のリストを返すことを意味します。つまり、zipWithは反復処理のケースをとります。反復処理のすべての項目で何をしたいのかを指定するだけで済みます。その場合は、対のペア(最初の行列からの行列、2番目の行列からの行列)。

zipWithに渡される関数は、各ペアからsnd要素を取り出し、その差を計算します。 zipWith署名を振り返ると、数字のリストが返されることを推測できます。したがって、最後に行うべきことは、関数sumを使用してそれらを合計することです。

最後に問題があります。私たちは実際にzipWith!に渡すべき2つの対のリストを持っていませんが、2つの行列です。要素の順序を保持したままリスト内で「平坦化」する必要があります。それはちょうどconcatが何であるかであり、したがって、flatM1flatM2という定義でその関数への呼び出しがあります。

私は、反復が反復の平均によってどのように表現されるかをよりよく把握するために述べたすべての関数の実装を調べることをお勧めします。 HTH

+0

ありがとう!素晴らしい仕事をした。 – Schytheron

+1

@Schytheron:行列だけでなく、その和だけでなく、相違が必要な場合は、構造体を 'concat'で平坦化するのではなく、' zipWith(zipWith diffSnd) 'のようなものを使うこともできます。また、 '' Data.Function'から 'on'を使って' 'diffSnd =( - )' on' snd''を実行します。 –

関連する問題