5

多くの場合、複数の関数を同じデータにマップする必要があります。これを行うためにdpMapを実装しました

dpMap fns = (`map` fns) . flip ($)

dpMap は 1 つの関数です。これは、データ dt を 1 回だけ読み取ることを意味しますか?

例として、リスト dt の最小値と最大値を計算することを検討してください。

minimax dt = (dpMap [minimum, maximum]) dt

(dt を取り除くことはできますが、-XNoMonomorphismRestriction を使用する必要があります)

このようなポイントフル形式で同じ関数を実装するよりもパフォーマンス上の利点はありますか?:

minimax2 dt = [minimum dt, maximum dt]

編集:定数メモリで動作する dpMap の一般的な実装はありますか?

別の素敵なブログ投稿を見つけました: http://www.haskellforall.com/2013/08/composable-streaming-folds.html ;これが役に立てば幸いです。

EDIT2:もう少しコンテキストの後、ここに解決策があります.dpMapの正確な実装はありませんが、パターンは十分に単純であるため、別の機能を保証しません:

minimax = (,) <$> minimum <*> maximum

使用法:

> minimax [1..100]
(1,100)

合計と長さも計算したい場合

func = (,,,) <$> minimum <*> maximum <*> sum <*> length

使用法:

> func [1..100]
(1,100,5050,100)

4

2 に答える 2

3

主にWillNessの回答の下にコメントがあるため、この回答の質問についてかなり広い見方をします。

ブログ投稿で、Max Rabkin は折り畳みコンビネータに関するいくつかの研究を紹介しました。Conal Elliott はこのアイデアを採用し、さらにいくつかのブログ投稿と、ハッキングに関するZipFold パッケージを公開しました。この資料を読むことを強くお勧めします。短くてかなりアクセスしやすいです。ZipFold パッケージは、しばらく更新されていませんが、おそらく非常に便利です。

Edward Kmett の最近の傑作である には、いくつかの折り畳みコンビネータlensも含まれています。そのためだけに使用するかどうかはわかりませんが、とにかくレンズを使用している場合は、検討する価値があるでしょう.

別のアプローチは、並列処理を使用することです。あなたが書くなら

import Control.Parallel

minimax2 dt = let a = minimum dt
                  b = maximum dt
              in a `par` b `pseq` [a,b]

-threaded とリンクすると、スケジューラの気まぐれやminimax2月の満ち欠けなど (主にスケジューラと関数 IIRC の割り当てパターン) に応じて、一定の空間に近いもので実行することが可能になります。もちろん、これは信頼できる保証を提供するものではありませんが、実際にはうまく機能します。このアプローチを一般化するdpMapのは簡単なはずです。おそらく、下位レベルを直接Control.Parallel.Strategies使用するのではなく、または類似のものを使用することをお勧めします。par

最後に、ほとんどの iteratee 派生ライブラリは、この種のタスクの処理に非常に優れています。一般に、これらは、入力ストリームが生成および消費されるタイミングを明示的に制御します。では、 とほぼ同じことを行うsequence_iterateeを提供し、 とまったく同じことを行うものを追加し、いくつかの zip を提供します。これらはすべて定数空間で実行されます (使用する関数自体が定数空間である場合)。他のほとんどのパッケージが同様の操作を提供していたとしても、私は驚かないでしょう。dpMapsequencedpMap

于 2013-04-30T09:02:47.500 に答える