I have three data declarations in the different modules:
data Data1 = Data1
{ id :: UUID
, field2 :: String
, field3 :: Int
}
data Data2 = Data2
{ id :: UUID
, field1112 :: String
, field4433 :: String
}
data Data3 = Data3
{ id :: UUID
, field22 :: Double
, field344 :: Int
}
And a class declaration:
class MyClass1 a where
method1 ....
How can I specify a constraint for MyClass1
so that only Data1, Data2 and Data3
can be instantiated by MyClass1
because they all have the field id
?
I tried the following, but it didn't seem right to me and I got errors:
-- in the different module
class MyDataBase a where
id :: a -> UUID
-- in the module Data1.hs
instance MyDataBase Data1 where
id d1 =
-- in the module Data2.hs
-- and so on....
class (MyDataBase a) => MyClass1 a where
method1 .... = -- calling
What about types you don't know about that also have that field?
In general, you can accomplish things like that with Lens (regular Haskell records are IMHO unusable); if you name your fields
_Data1Id
and_Data2Id
(customizable), you'll get aHasId
class withid
lens and instances for that class forData1
andData2
. Then you can use that class as a constraint further.Of course you don't have to use
makeFields
and you can write the instances yourself. Not sure why you'd do that, though.You didn't specify what errors you got, but I bumped off
UndecidableInstances
. Here's how to get around "Constraint is no smaller than the instance head" error:This will allow you to use any type that satisifies B in a A context (but as Carsten pointed out, it's also an antipattern of sorts).