4

、、、および次のような構文を使用して::*、C++の構造体メンバーへの相対ポインターを作成および参照できます。.*->*

char* fstab_t::*field = &fstab_t::fs_vfstype;
my_fstab.*field = ...

Haskellでは、次のようなレコードゲッター用の一時的なラベルを簡単に作成できます。

(idxF_s,idxL_s) = swap_by_sign sgn (idxF,idxL) ;

Afaik、しかし、これらのゲッターを次のようなラベルとして使用してレコードを更新することはできません。

a { idxF_s = idxL_s b }

各レコードセッターをコーディングせずにこれを行う簡単な方法はありますか?

4

2 に答える 2

9

ファーストクラスの値にバンドルされたゲッターとセッターは、レンズと呼ばれます。これを行うためのパッケージはかなりあります。最も人気のあるのはデータレンズfclabelsです。この前のSOの質問は良い入門書です。

これらのライブラリは両方とも、Template Haskellを使用したレコード定義からのレンズの導出をサポートしています(データレンズを使用すると、移植性のための追加パッケージとして提供されます)。あなたの例は次のように表現されます(data-lens構文を使用):

setL idxF_s (b ^. idL_s) a

(または同等にidxF_s ^= (b ^. idL_s) $ a:)

もちろん、ゲッターとセッターを一緒に変換することで、一般的な方法でレンズを変換できます。

-- I don't know what swap_by_sign is supposed to do.
negateLens :: (Num b) => Lens a b -> Lens a b
negateLens l = lens get set
  where
    get = negate . getL l
    set = setL l . negate

(または同等に:negateLens l = iso negate negate . l1

一般的に、重要なレコード処理を処理する必要がある場合は、レンズを使用することをお勧めします。レコードの純粋な変換を大幅に簡素化するだけでなく、両方のパッケージに、レンズを使用して状態モナドの状態にアクセスして変更するための便利な関数が含まれています。これは非常に便利です。(data-lensの場合、data-lens-fdパッケージを使用して、これらの便利な関数を任意の場所で使用することをお勧めしますMonadState。繰り返しになりますが、移植性のために別のパッケージに含まれています。)


1いずれかのパッケージを使用する場合は、モジュールを次のコマンドで開始する必要があります。

import Prelude hiding (id, (.))
import Control.Category

これは、プレリュードid(.)関数の一般化された形式を使用しているためidです。任意の値からそれ自体までレンズとして使用でき(確かに、それほど有用ではありません)、(.)レンズを構成するために使用されます(たとえばgetL (fieldA . fieldB) a、と同じgetL fieldA . getL fieldB $ aです)。短いnegateLens定義ではこれを使用します。

于 2012-02-04T19:57:13.577 に答える
5

ここで必要なのはファーストクラスのレコードレーベルです。これはこの言語には存在しませんが、Hackageにはこのパターンを実装するパッケージがいくつかあります。これらの1つはfclabelsで、TemplateHaskellを使用して必要なボイラープレートを生成できます。次に例を示します。

{-# LANGUAGE TemplateHaskell #-}

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

data Foo = Foo { _fieldA :: Int, _fieldB :: Int }
  deriving (Show)

$(mkLabels [''Foo])

main = do
  let foo = Foo 2 3

  putStrLn "Pick a field, A or B"
  line <- getLine

  let field = (if line == "A" then fieldA else fieldB)

  print $ modify field (*10) foo
于 2012-02-04T20:07:35.457 に答える