I want to implement a Type Class
with few default methods, but I'm getting an error, that I cannot use record selectors
inside type classes
definitions.
The following code basically creates type class
which defines add
function, which should add an element to the repr
record of some data type
. Here is the code:
import qualified Data.Graph.Inductive as DG
class Graph gr a b where
empty :: DG.Gr a b
empty = DG.empty
repr :: gr -> DG.Gr a b
-- following function declaration does NOT work:
add :: a -> gr -> gr
add el g = g{repr = DG.insNode el $ repr g}
The compiler throws error:
repr is not a record selector
In the expression: g {repr = DG.insNode el $ repr g}
In an equation for add:
add el g = g {repr = DG.insNode el $ repr g}
Is it possible to declare such methods in Haskell?
Clarification
I need such design because I've got some data types
, which behave in simmilar way. Lets say, we got A
, B
and C
data types
. Each of them should have a record repr :: DG.Gr a b
, where a
and b
are distinct for each of A
, B
and C
.
A
, B
and C
share the same functions, like add
or delete
(which basically add or delete elements to record repr
). If these data types share a lot of functions it make sense to implement the functions in type class
and make instances of this type class
- these functions will be implemented for each of our data type
automatically.
Additional I would love some of these data types
(lets say I want B
) to behave slighty different when calling add
function on it. It is easy to implement this behaviour when making instance
of the type class
for B
.
The record update syntax
works when
<record-instance>
is an instance/term of a known algebraic data type (so that<record-field-name>
is it known field), in your code it is just some (ad-hoc) polymorphic parametergr
, so you need first to convertgr
toGr
, then update it, and then...I think that
gr
andGr
should be equivalent in some sense, i.e. we need an inverse function forrepr
, sayiface
, to be able to implementadd
.Here is an example:
If some data types
A
andB
aggregateGr a b
(so that we can't write an inverse forrepr
), then we can do something like this:It is also possible to use lenses here:
You can try something like this (which uses tuple list as example instead of
DG
)