Closed UnkindPartition closed 7 years ago
Interesting. I'm willing to add it, yes. Just struggling with naming. Perhaps something like this:
expand_NS :: forall xs f . SingI xs => NS (f -.-> f) xs -> NP (f -.-> f) xs
expand_NS ns = case sing :: Sing xs of
SCons -> case ns of
Z f -> f :* hpure (Fn id)
S ns' -> Fn id :* expand_NS ns'
expand_SOP :: forall xss f . SingI xss => SOP (f -.-> f) xss -> POP (f -.-> f) xss
expand_SOP (SOP sop) = case sing :: Sing xss of
SCons -> case sop of
Z np -> POP (np :* unPOP (hpure (Fn id)))
S sop' -> POP (hpure (Fn id) :* unPOP (expand_SOP (SOP sop')))
class (Prod (Prod h) ~ Prod h) => Expandable (h :: (k -> *) -> (l -> *)) where
hexpand :: SingI xs => h (f -.-> f) xs -> Prod h (f -.-> f) xs
instance Expandable NS where
hexpand = expand_NS
instance Expandable SOP where
hexpand = expand_SOP
mapSingle :: (SingI xs, Expandable h, HAp (Prod h)) => h (f -.-> f) xs -> Prod h f xs -> Prod h f xs
mapSingle ns np = hexpand ns `hap` np
Looks good.
Sorry, but I'm going to not include this in 0.2 just yet. I'm still planning to do this, though. I'm just still thinking about the <*>
stuff for NS/NP combinations, and may move away from the name hap
for these, as I think it's actually confusing.
Ok, no problem.
@feuerbach Just looked at this again due to the mention in https://ro-che.info/articles/2015-07-26-better-yaml-parsing
I think that
hap' = flip (hzipWith (flip apFn))
@feuerbach Ah no, my mistake. The result type is wrong.
Are we looking for Defaultable1 f => NS f xs -> NP f xs
function here, I don't think it make sense to restrict ourselves to g -.-> g
function type, but I'm not sure wha's the right type-class for f
would be.
alternatively hset :: NS f xs -> NP f xs -> NP f xs
would make sense, but then it generalises to the original hap'
hApplyInj :: (forall a. f a -> g a -> g a) -> NS f xs -> NP g xs -> NP g xs
Not sure this is the same thing at all but I have recently found use (in https://github.com/adamConnerSax/perConstructor-sop ) for:
expand::forall (f :: [k] -> *) xs.(SListI xs)=>NS f xs -> NP (Maybe :.: f) xs
expand ns = go sList (Just ns) where
go::forall ys.SListI ys => SList ys -> Maybe (NS f ys) -> NP (Maybe :.: f) ys
go SNil _ = Nil
go SCons mNS = case mNS of
Nothing -> Comp Nothing :* go sList Nothing -- after Z
Just ms -> case ms of
Z fx -> Comp (Just fx) :* go sList Nothing -- at Z
S ms' -> Comp Nothing :* go sList (Just ms') -- before Z
which seems like it might of the same ilk, though not quite. I see why "Defaultable1 f" (I don't know what that is and googling is not helping but I can guess and it makes sense.) would be useful. Though the version I had use for was general in the f but required something like Maybe to compose with. Though perhaps (Maybe :.: f) is Defaultable1 (?) and then my case is essentially covered?
I'm a beginner with generics-sop (and markdown!), so forgive me if this is not a useful contribution to the discussion.
Adam
@phadej I think generalizing past the function type makes sense. We could get around the need for an additional type class by explicitly passing in the default. Something like
expand_NS :: SListI xs => (forall x . f x) -> NS f xs -> NP f xs
cexpand_NS :: All c xs => proxy c -> (forall x . c x => f x) -> NS f xs -> NP f xs
(and similar functions for SOP
and POP
).
Then AFAICS, the function @adamConnerSax needs is just
expand :: SListI xs => NS f xs -> NP (Maybe :.: f) xs
expand = expand_NS (Comp Nothing) . hmap (Comp . Just)
After all this time, I've actually implemented this and made a PR (#33). Feedback welcome.
@feuerbach I hope that the expand
functions as now merged via #33 are useful, and that a separate hap
variant is then not needed anymore.
Yes, now the code is much simpler. Thanks!
Here's an alternative generalization of
<*>
:Unless I'm missing something, it can't be implemented in terms of the existing combinators. If so, I suggest adding it under some name.