Using the generics-sop
library, I have the following function:
f :: (Applicative m) => (forall b. m (ref b)) -> m (NP I '[ref x1, ref x2])
f act =
sequence_NP (act :* act :* Nil)
How would I generalize this to a n-product i.e. with act
in every position, polymorphic to the return type?
The relevant definitions are:
data NP :: (k -> Type) -> [k] -> Type where
Nil :: NP f '[]
(:*) :: f x -> NP f xs -> NP f (x ': xs)
sequence_NP :: (SListI xs, Applicative f) => NP f xs -> f (NP I xs)
The obvious approach is to use pure_NP
pure_NP :: forall f xs. SListI xs => (forall a. f a) -> NP f xs
as follows:
f :: (Applicative m, _) => (forall b. m (ref b)) -> m (NP I refs)
f act =
sequence_NP (pure_NP act)
but this doesn't compile:
• Could not deduce: a ~ ref b0
from the context: (Applicative m, All Top refs)
bound by the inferred type of
f :: (Applicative m, All Top refs) =>
(forall b. m (ref b)) -> m (NP I refs)
at /home/ari/fcm-deepref-experiment/test/QuickCheck.hs:(163,1)-(164,27)
‘a’ is a rigid type variable bound by
a type expected by the context:
forall a. m a
at /home/ari/fcm-deepref-experiment/test/QuickCheck.hs:164:24-26
Expected type: m a
Actual type: m (ref b0)
• In the first argument of ‘pure_NP’, namely ‘act’
In the first argument of ‘sequence_NP’, namely ‘(pure_NP act)’
In the expression: sequence_NP (pure_NP act)
• Relevant bindings include
act :: forall b. m (ref b)
(bound at /home/ari/fcm-deepref-experiment/test/QuickCheck.hs:163:3)
f :: (forall b. m (ref b)) -> m (NP I refs)
(bound at /home/ari/fcm-deepref-experiment/test/QuickCheck.hs:163:1)
because it expects all the act
s to be of the same type, but they're not: it has a polymorphic type.
I'm assuming I should be using cpure_NP
,
cpure_NP :: forall c xs proxy f. All c xs => proxy c -> (forall a. c a => f a) -> NP f xs
the constrained version pf pure_NP
, but I can't work out how to set up the constraint.