2011-12-14 7 views
6

私はこのようになりますいくつかのHaskellの決まり文句がありますHaskellの動的データ・タイプの変更

data Configuration 
    { confA :: Integer 
    , confB :: Boolean 
    , confC :: String } 

x = (\arg opt -> opt{ confA=arg }) 
y = (\arg opt -> opt{ confB=arg }) 
z = (\arg opt -> opt{ confC=arg }) 

を、私はの線に沿って何かを得、定型を削除したい:

setter :: (Config -> a) -> a -> Config -> Config 
x = setter confA 
y = setter confB 
z = setter confC 

しかし、私はそのようなsetter関数をどのように構築するのか分かりません。これは(テンプレートではない)haskellでも可能ですか、ここで構文の砂糖にぶつかっていますか?もしそうなら、テンプレートのhaskellでどうすればいいですか?

答えて

13

これは、Haskellの記録システムだけでは不可能です。あなたが望むのはレンズです。このprevious Stack Overflow questionとその最高の回答は良い紹介です。個人的には、私はそこで話したdata-lensパッケージを使用します。 (MTLからMonadStateクラスでそれを使用することもdata-lens-fdを参照してください - あなたはそれが何であるかわからない場合は、ちょうどあなたがStateモナドでレンズを使いたいときにいつでも、おそらくそれを使用する必要があることを知っている。)

data-lens-templateパッケージはあなたが望むTemplate Haskellのアプリケーションかもしれません。レコードフィールドのレンズ定義を導出します。

他の一般的なレンズパッケージはfclabelsです。私はそのシンプルさとスピードのためにデータレンズを好む。 fclabels(バージョン1.0現在)は少し柔軟性がありますが、あなたがやりたいことに柔軟性は必要ありません。 (新しく増した柔軟性のために、fclabelsの(:->)タイプは、リンクされたスタックオーバーフローの回答に記載されているように、レンズの単純な定義に直接変換できません)。

1

テンプレートハスケルなしではこれはできません。このようなボイラープレートを取り外すには、データアクセッサとデータアクセッサテンプレートを使用できます。

+0

これは正しいと思います。レコード構文は自動的に* getters *を作成しますが、* setters *を作成する場合はほとんど役に立ちません。 –

関連する問題