2011-12-29 14 views
3

基本的には、更新可能なリストを含むタプル(または私の問題に合った任意のデータ型)を達成したいと思います。不変性のため、そのようなデモンストレータコードはもちろん動作しません。私が達成したいことをより良く説明することだけです。タプルで囲まれた更新リスト

エレガントな方法、データ型(IOREfs?)、または私のためにそれを行うモジュールがあるのだろうか、そういう場合には本当にタプル全体を分解し、更新された要素。

ところで、直感的に私は、少なくともテストが印刷されない限り、リストmsgは評価されないと予想していました。他の人が述べたように

test = ("192.168.1.1", 3455, (1234566, msgs)) 
msgs = ["aaa", "bbbb", "ccccc"] 

main = do 
    --print test 
    let msg_tmp = "first" : msgs 
    let msgs = msg_tmp 
    print msgs 
    print test 
+1

はあなたが本当に可変性を求めている、またはあなただけのいくつかの不変データの新しいバージョンを作成するための簡単な方法をしたいですか?前者の場合は、それを再考してください。特に、あなたが可変性を可能にする言語から来た場合。 – delnan

+0

私はいくつかの不変のデータの新しいバージョンを作成する "最小のコストでシンプルな方法を探したい"。 –

+1

"コスト"を定義します。あなたはパフォーマンスについて心配していませんか?もしそうなら、あなたには恥ずかしいです。学習に戻る;) – delnan

答えて

1

あなたはlensesを使用して考えられてきたように、あなたはあなたの例を実装することができ、そのような

modifyMessages :: ([String] -> [String]) -> MyRecord -> MyRecord 
modifyMessages = -- Left as an exercise for the student 

として、独自の修飾子を書くべきですか?あなたの目的がタプルをプログラマにとって簡単で透明に更新することであるならば、それらは非常にうまくその法案に適合します。

import Data.Label 
import Control.Category 
import Prelude hiding ((.)) 


test = ("192.168.1.1", 3455, (1234566, msgs)) 
msgs = ["aaa", "bbbb", "ccccc"] 

append x = modify messages (x :) 

main = do 
    let test' = append "first" test 
    print test' 
    print (get messages test') 

second2 = lens (\(a,b) -> b) (\b (a,_) -> (a,b)) 
third3 = lens (\(a,b,c) -> c) (\c (a,b,_) -> (a,b,c)) 
messages = second2 . third3 

second2third3はあなたが必要とするすべてのタプルに対して一度定義 汎用的な機能のいずれかであることができる、または、彼らはmessages、またはtimestampのような意味のある名前で何か ことができます。以下は、優れたfclabelsパッケージを使用しています。とにかく、この は、一度書かれてからライブラリに隠されたものです。

GHCiの持つテストは望ましい結果が得られます。

ghci> :main 

("192.168.1.1",3455,(1234566,["first","aaa","bbbb","ccccc"])) 
["first","aaa","bbbb","ccccc"] 
+0

ありがとう!レンズは素晴らしいアイデアで、私にとってはうまくいきます。 –

3

、物事に機能的な方法をしていないために非常に具体的かつ重いな理由があるはずです。あなたのタプルは不複雑そうですが、あなたは、このような余分なメッセージと新しいものを作成に取り掛かることができます:

addMsg (a,b,(c,msgs)) msg = (a,b,(c,msg:msgs)) 
2

あなたが言うように、Haskellは不変のデータ型を使用しています。 mutableのようなことをするためのSTRefとIORefがありますが、もしあなたがHaskellを学んでいるなら、まずは不必要なことを最初からやりたいのです。

ハスケルにはレコードアクセサがありますが、タプルはありません。

data MyRecord { 
    ipAddress :: String, 
    magicNumber :: Integer, 
    messages :: [String] 
} deriving Show 

この場合、フィールド名をフィールドのget関数として使用することができます。

test = MyRecord "192.168.1.1" 12345 ["aaaa", "bbbb", "cccc"] 

を考えると、あなたは表現「messgesテスト」を使用してメッセージを取得することができ、またはIOモナドで:

print $ messages test 

あなたは、いくつかの特別なシンタックスシュガーを使用して「テスト」の新バージョンを作成することができます

test2 = test {magicNumber = 654321} 

これは、異なるmagicNumberフィールドを除いて、test2をテストのコピーに設定します。

だからあなたが言うことができる:

私は少し不格好ですが、実際には非常に多くの場合、それを必要としない同意
test3 = test {messages = "first" : messages test} 

を。

ハスケルのための改良された記録システムのために浮上しているいくつかの提案があります。上記の構文的な砂糖は実際に機能になりますが、それらの後ろにコンセンサスはありません。必要な場合はおそらく

test4 = modifyMessges ("first" :) test 
+0

ありがとうございます。実際、Haskellのコードはしばしばとてもよく見えるので、test1、test2、test3などのような "clunky"なものは本当に真実であるとは信じられませんでした。私はちょうど私がまだ出くわしていない非常にエレガントなものを見つけることを望んだ。 –

関連する問題