Some pseudocode:
data A = A
data B = B
data C = C
data D = D
data E = E
data F = F
data G = G
data A1 = A1 A B C
data A2 = A2 A
data A3 = A3 B C D
data A4 = A4 D E F
data A5 = A5 A1 A4 G
data Foo k = Foo
{
a1s :: Map.Map k A1,
a2s :: Map.Map k A2,
a3s :: Map.Map k A3,
a4s :: Map.Map k A4,
a5s :: Map.Map k A5,
--and my attempted solution would use
-- e.g. [(A1, [(A, Unit), (B, Unit), (C, Unit)]), (A5, [(A1, Composite), (A4, Composite), (G, Unit) ]) ]
componentMap :: Map.Map Type (Set Type),
-- e.g. [(A, [A1, A2]), (A1, [A5, A1]) ]
compositeMap :: Map.Map Type (Set Type)
}
I'd like to construct some kind of data structure that looks like this. From here, I'd like to:
lookup :: Foo k -> k -> Either FailureReason v
individual values; if we assume that we have populated maps, I'd likelookup foo a1 :: A1
, but also transitive instances such aslookup foo a1 :: B
orlookup foo a5 :: A1
(since this is shorthand forgetA1fromA5 $ lookup foo a5
) andlookup foo a5 :: B
. I'm consideringFailureReason = WrongType | NotPresent
but this is probably excessive.- traversals over types such as an (indexed) traversal over
(k, D)
which should hit everything inA3, A4, A5
This could be implemented as a recursive search over componentMap
and compositeMap
..so long as they were populated by hand.
Since the above seem very much recursive, I feel this has a GHC.Generics
solution. Possibly a lens/optics + generic-lens/generic-optics
one?
Or is my solution one that doesn't need generics
and its ilk, and is instead just writing some traversals and lenses to index into my structure?
The question then becomes: is this functionality already existing in some library? If not, is Generics
the tool I'm looking for to implement it?