I\'ll just say I\'m not even sure if this is possible; it is by far the most generic thing I\'ve tried doing in Haskell. I\'m trying to make a more generic version of the
I can't be sure this will fix everything, because it's very hard to reproduce your problem: it requires a lot of packages and imports that I just don't have the time to set up (hint: in the future, try to reduce your problems to minimal reproducible examples before posting). But I'm going to post this anyway, because I can see at least one problem, and it seems to be related to the error message.
The problem is that t
on the first line is not the same as t
on the third line, and they are both different from the t
on the fifth line. And so on, for all type signatures involving t
.
By default, in Haskell2010 every type variable's scope is only the type signature in which it's introduced. If you use the same letter in another type signature, it will signify a completely separate type, despite looking identical to the human eye.
To specify that you actually mean t
to be the same everywhere, you have to use forall
in the top type signature:
applyRecFun :: forall t. (Traversable t, _) => Record (SummaryFun t) _ -> t r -> r
Enabled by the ScopedTypeVariables extension, the forall
keyword creates an explicit scope for the type variable t
. Scopes come in different flavors, but when opened in a function's type signature, the scope's extent is the whole body of that function.
I'm not sure this will solve everything for you, but at least you should be getting different errors now.
Building on Fyodor's answer, I have a compiling (but as yet untested) code. I had to change a few assumptions in the type signature, such as returning the result wrapped in Maybe
, and assuming the Traversable
also forms a Semigroup
. I'll revise the wording of the question and this answer once I've had a chance to properly test and construct a self-contained example as suggested by Fyodor:
newtype SummaryFun t a = SummaryFun (t a -> a)
applyRecFun :: forall r t. (Traversable t, Semigroup (t r), _) =>
Record (SummaryFun t) _ -> t r -> Maybe r
applyRecFun func recs =
let recsNP :: t (NP I _) -- a traversable of n-ary products. I is an identity functor
recsNP = toNP . toRecord <$> recs
listrecsNP :: t (NP t _) -- turn every component into a singleton traversable
listrecsNP = liftA_NP (\(I x) -> pure x) <$> recsNP
listrecNPmay :: Maybe (NP t _) -- a single n-ary product where each component is a traversable
listrecNPmay = listrecsNP & (headMay &&& tailMay) & sequenceT
<&> (\(h, t) -> foldr mappend h t)
funcNP :: NP (SummaryFun t) _ -- turn the function record into a n-ary prod
funcNP = toNP func
toRec_NP_I :: NP t _ -> NP I _ -- apply the functions to each list component
toRec_NP_I = liftA2_NP (\(SummaryFun f) vs -> I (f vs)) funcNP
in do
listrecNP <- listrecNPmay
let resultRec_NP_I = toRec_NP_I listrecNP
pure $ fromRecord . fromNP $ resultRec_NP_I -- go back to the nominal record Rec