次のデータ型が定義されているとします。
data X a = X {getX :: a}
data Y a = Y {getY :: a}
data Z a = Z {getZ :: a}
getX
、getY
、およびの 3 つの別個の関数が存在する必要がありますgetZ
か? 次のように定義された関数が存在する可能性があるように私には思えます。
get :: forall (τ :: (* -> *)) (a :: *). τ a -> a
get (_ x) = x
明らかに、これは有効な標準 Haskell ではありませんが、GHC には非常に多くの拡張機能があり、解決策があるようです ( RankNTypes
、ExistentialQuantification
、DataKinds
など)。少量のタイピングを回避するという単純な理由に加えて、レコード ソリューションによって作成される名前空間の汚染を回避するという利点があります。これは、次のような型クラスを使用するよりも、実際にはより暗黙的な解決策であると思います。
class Get f where
get :: f a -> a
ただし、ジェネリック関数を定義する方が型クラスよりも有用であるように思われます。これは、暗黙的に定義されているという事実は、($)
or(.)
が使用されるのと同じ方法で、より多くの場所で使用できることを意味するためです。したがって、私の質問には 3 つの部分があります。これを達成する方法はありますか、それは良い考えですか、そうでない場合、より良い方法は何ですか?