質問

data.memocombinators ですが、その中心がどこにあるのか本当にわかりません。

これらのコンビネータのすべての背後にあるものは、実際の世界のプログラミングでプログラムをスピードアップする方法ののすべての背後にあるものを説明してください。

この実装の詳細を探しています。私はどのようなメモイケーションが何であるかを理解していますではありません一般的に機能する方法についての説明を探しています。

役に立ちましたか?

解決

このライブラリは、メモリ化の公知の技術の直接的な組み合わせです。正規の例から始めましょう:

fib = (map fib' [0..] !!)
    where
    fib' 0 = 0
    fib' 1 = 1
    fib' n = fib (n-1) + fib (n-2)
.

あなたが言ったことをあなたがこれがどのように機能しているのかと理由を知っているということを意味するものを解釈します。だから私は組み合わせに焦点を当てます。

私たちはESSENTIALLに(map f [0..] !!)のアイデアを把握し、一般化しようとしています。この関数のタイプは(Int -> r) -> (Int -> r)です。これは意味があります.Int -> rから関数がかかり、同じ関数のメモイマバージョンを返します。意味的に識別的なものであり、このタイプを持つ関数は、 "Intのメモイザ"と呼ばれます(Meidさえ、メモイクではありません)。この抽象化に一般化します。

type Memo a = forall r. (a -> r) -> (a -> r)
.

それで、Memo a用のメモイザは、aから何でも関数を取り、メモリングされた(またはそうでない)意味的に同じ関数を返します。

さまざまなメモイザーのアイデアは、データ構造を持つドメインを列挙する方法を見つけ、それらの上に関数をマッピングしてからデータ構造を索引付けします。 aは良い例です:

bool :: Memo Bool
bool f = table (f True, f False)
    where
    table (t,f) True = t
    table (t,f) False = f
.

boolからの関数はペアと同等です。だから私たちはペアとバックにマッピングするだけです。重要な点は、ドメインを列挙することによって、引数(ここではBoolの最後の引数)のラムダの上の関数の評価を持ち上げることです。

Memoizing tableは、紹介されている以外は同様のストーリーです。そのため、Maybe a用のメモイザは、a用のメモイザを引数として取ります。

maybe :: Memo a -> Memo (Maybe a)
maybe ma f = table (f Nothing, ma (f . Just))
    where
    table (n,j) Nothing = n
    table (n,j) (Just x) = j x
.

残りのライブラリはこのテーマの単なるバリエーションです。

整数型をメモリングする方法は、Justよりも適切な構造を使用します。それは少し関わっていますが、基本的には無限のツリーを作成するだけです(構造を解明するためのバイナリの数字を表す):

1
  10
    100
      1000
      1001
    101
      1010
      1011
  11
    110
      1100
      1101
    111
      1110
      1111
.

ツリー内の数字を見上げると、その表現のビット数に比例して実行時間があります。

SCLVを指すように、ConalのMemotrie Libraryは同じ基本的なテクニックを使用していますが、コンビネータプレゼンテーションの代わりに型抜きプレゼンテーションを使用します。私たちは同時にライブラリを同時にリリースしました(確かに数時間以内です)。 CONALの簡単な場合では使いやすい(関数、Maybeは1つだけです。

boundedMemo :: Integer -> Memo Integer
boundedMemo bound f = \z -> if z < bound then memof z else f z
   where
   memof = integral f
. Project Eulerの問題の1つを実装するために必要な値の値のみをメモリ化する

モナド上のオープンフィックスポイント機能を公開するための他のアプローチがあります。

memo :: MonadState ... m => ((Integer -> m r) -> (Integer -> m r)) -> m (Integer -> m r)
.

それはさらに柔軟性を可能にします。キャッシュ、LRUなどをパージすることは、使用するためのお尻の痛みであり、また思い出される機能に厳密さの制約を与えます(例えば、無限の左再帰はありません)。このテクニックを実装するライブラリがあるとは思わない。

それはあなたが興味があるものに答えましたか?そうでなければ、おそらくあなたが混乱しているポイントを明確にする?

他のヒント

作品の中には、inttrieによって行われています:> http://hackage.haskell .ORG /パッケージ/データ-TTRIE-0.0.4

ルークのライブラリは、ConalのMemotrie Libraryのバリエーションです。 http://conal.net/blog/posts/elegant-moization-with-functional-memo-tries/

機能メモリングの背後にある一般的な概念は、a -> bから関数を取り、aのすべての可能な値とbの値を含むデータストラクチャを中心にマッピングすることです。そのようなデータストラクチャは2つの方法で怠惰になるべきです - 最初にそれが保持する値で怠惰になるべきです。第二に、それはそれ自体が怠惰に生産されるべきです。前者はデフォルトではない言語であります。後者は一般化試行を使用することによって達成されます。

メモンビネット、メモトリエなどのさまざまなアプローチはすべて、ますます複雑な構造のための試みの簡単な構造を可能にするために、個々の種類のデータストラクチャに対抗する部分の組成を作成する方法だけです。

@luqui私には明確でないことを1つ:これは次のように同じ運用行動を持っていますか:

fib :: [Int]
fib = map fib' [0..]
    where fib' 0 = 0
             fib' 1 = 1
             fib' n = fib!!(n-1) + fib!!(n-2)
.

上記は上位レベルでFIBをメモリングする必要があり、したがって2つの関数を定義する場合:

f n = fib!!n + fib!!(n+1)
.

その後 F 5 を計算した場合、 FIB 6 を計算する際に FIB 5 <>は再計算されない。メモイズコンビネータが同じ動作(すなわち、FIB計算の中の再計算を禁止するのではなくトップレベルのメモイ化)であるかどうかは明らかではなく、そうであれば、正確には正確に?

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top