2009-03-07 20 views
4

特定のオブジェクトを使用できないときに読み込むことができる透過キャッシュを実装しようとしています。つまり、(name)でインデックスされた既存のオブジェクトを返すことができます。キャッシュを実装する

loader' objs name = case findObj objs name of 
    Nothing → (new_obj, loader' new_objs) 
    Just obj → (obj, loader' objs) 
    where 
    new_objs = [(name, new_obj)] ++ objs 
    new_obj = readObj name 
loader = loader' [] 

が、私はまさに私が:)

をしたい何かのように見えます

 
Occurs check: cannot construct the infinite type: 
    t = (ObjType, String -> t) 

を取得していますどのように機能を修正することができます。これは、実行中の

私が試してみましたそれはコンパイルするように?

明確化:要求され、署名(findobjをキー経由で見つかった既知の値を返すか、何も、readObjは、キーの新しいOBJを作成する)として

findObj :: [(String, ObjType)] -> String -> Maybe ObjType 
readObj :: String -> ObjType 

そして、はい - 私はキーはファイル名であり、何らかのオブジェクトが必要になるたびにファイルを読み込み+解析したくないので、キャッシュが必要です。

+0

findObjとreadObjの定義を参照する必要があると思います –

+0

機能的な言語でキャッシュの概念が必要なのでしょうか? 私はいつもそれが命令的な最適化だと思っていました。 – Pyrolistical

+0

findObj、readObjのシグネチャが追加されました – viraptor

答えて

2

つの思考(野生推測?)それはJust obj句で、および/またはreadObj nameから右の型シグネチャを生成するために失敗しているかのように見え、このような何かしようとするも面白いかもしれません:

loader' :: [(String, ObjType)] -> String -> (ObjType, String -> ObjType) 
loader' objs name = case findObj objs name of 
    Nothing → (new_obj, loader' new_objs) where 
    new_objs = [(name, new_obj)] ++ objs 
    new_obj = readObj name 
    Just obj → (obj, loader' objs) 
loader = loader' [] 

私はそれがそれを修正すると言っているわけではありません(しかし、それはそうかもしれないと思います)。むしろ、私はそれが問題をより理にかなったものに変え、そうでなければ状況を明らかにするかもしれないと言っています。

編集:キャッシュタイプに名前を付けるのトムLokhorstの提案を適用する

はこれに私たちをリード:それは問題が何であるか明らかになり

type Cache = [(String, ObjType)] 
loader' :: Cache -> String -> (ObjType, ????) 
loader' objs name = case findObj objs name of 
    Nothing → (new_obj, loader' new_objs) where 
    new_objs = [(name, new_obj)] ++ objs 
    new_obj = readObj name 
    Just obj → (obj, loader' objs) 
loader = loader' [] 

を。 loader 'の2番目の結果の型は文字列を取る関数で、ObjTypeと文字列を取る関数からなる対が生成され、ObjTypeと文字列を取る関数で構成される対が生成され、 ObjTypeと文字列を取る関数で構成され、ObjTypeと...からなるペアを生成します。あなたは画像を取得します。あなたはこのようにそれを書き換える場合

type Cache = [(String, ObjType)] 
loader' :: Cache -> String -> (ObjType, Cache) 
loader' objs name = case findObj objs name of 
    Nothing → (new_obj, new_objs) where 
    new_objs = [(name, new_obj)] ++ objs 
    new_obj = readObj name 
    Just obj → (obj, objs) 

それはコンパイルする必要がありますが、あなたは、あなたがそれを使用する方法を変更する必要があります。

0

haskellのキャッシングのthis implementationを参照してください。

+0

重いものが必要なのではないかと思っています - シングルスレッドのファイルローダが必要です... また、私は一般的に問題を解決する方法を知りたかったので、部分的に適用されます) – viraptor

2

どうしてですか?memoize findObj?

2

Haskellはこのようなタイプをサポートしていません:コンパイラはそれをチェック入力し、このタイプを展開しようとするため

type t = Int -> t 

です。型システムは厳密に終了するので、型チェック中に無限ループが発生します。あなたがこれをやることができるよりも、もっと怠惰な型のシステムを持つことはいいですが、それは現時点ではHaskellを持っていません。

しかし、MarkusQによれば、関数loader'の変更だけで簡単です。キャッシュと答えと(おそらく更新)キャッシュの両方を返す検索文字列を、取る機能です

type Cache = [(String, ObjType)] 

loader' :: Cache -> String -> (ObjType, Cache) 

:私は、私はそれをこのように書くと思います。

+0

名前の変更と私の再構成の組み合わせは、問題が何であるかをはっきりと示しています。キャッシュの名前をつけるというあなたの考えを使って私の答えを修正しました。 – MarkusQ

関連する問題