2

次のようないくつかのデータ構造があります

data Data1 = Data1
    { _data1Field :: Int
    -- More fields
    } deriving (Eq, Show)
makeLenses ''Data1

data Data2 = Data2
    { _data2Field :: Int
    -- More fields
    } deriving (Eq, Show)
makeLenses ''Data2

-- More similar data types

そこで、簡単に作成できるように単純な型クラスを作成することにしました

class HasField a where
    field :: Lens' a Int

instance HasField Data1 where
    field = data1Field

instance HasField Data2 where
    field = data2Field

しかし、これらの構造の一部に対応するフィールドがオプションとしてあるという問題に遭遇しました

data Data3 = Data3
    { _data3Field :: Maybe Int
    -- More fields
    } deriving (Eq, Show)
makeLenses ''Data3

そして今、型クラスを使用できなくなりました。そのフィールドがオプションではないデータ型とほぼ同じ数のデータ型があるため、型クラスを変更する方がよいと判断しました。

class HasField a where
    field :: Lens' a (Maybe Int)

instance HasField Data3 where
    field = data3Field

しかし、私はレンズ ライブラリの経験があまりないので、この新しいレンズをData1およびの型で機能させる方法を考え出すのに苦労していますData2。理想的には、それを表示してMaybe Int任意のタイプの値を取得できるようにしたいと思います。設定するときJust xは、フィールドをxforData1とに設定しData2、渡されたときにこれら 2 つのタイプの操作を行わないようにしたいと考えていNothingます。

これは既存のコンビネータを使用して可能ですか、それとも自分でレンズを作成する必要がありますか? 私はそうしても問題ありませんが、既存のチュートリアルの大半は TH を使用しており、手書きでの記述の詳細については触れていません。

GHC 7.6.3 とlens3.10 を使用しています。

4

1 に答える 1