Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Zip NP and NS to produce NP #11

Closed
UnkindPartition opened this issue Jul 13, 2015 · 13 comments
Closed

Zip NP and NS to produce NP #11

UnkindPartition opened this issue Jul 13, 2015 · 13 comments
Milestone

Comments

@UnkindPartition
Copy link
Contributor

Here's an alternative generalization of <*>:

hap' :: forall f (xs :: [k]) . NS (f -.-> f) xs -> NP f xs -> NP f xs
hap' (Z (Fn f)) (h :* t) = f h :* t
hap' (S f) (h :* t) = h :* hap' f t
hap' _ _ = error "impossible"

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.

@kosmikus
Copy link
Member

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

@UnkindPartition
Copy link
Contributor Author

Looks good.

@kosmikus
Copy link
Member

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.

@UnkindPartition
Copy link
Contributor Author

Ok, no problem.

@kosmikus
Copy link
Member

kosmikus commented Mar 6, 2017

@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))

@kosmikus
Copy link
Member

kosmikus commented Mar 6, 2017

@feuerbach Ah no, my mistake. The result type is wrong.

@phadej
Copy link
Contributor

phadej commented Mar 6, 2017

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.

@phadej
Copy link
Contributor

phadej commented Mar 6, 2017

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

@adamConnerSax
Copy link
Contributor

adamConnerSax commented Apr 13, 2017

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

@kosmikus
Copy link
Member

@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)

@kosmikus
Copy link
Member

After all this time, I've actually implemented this and made a PR (#33). Feedback welcome.

@kosmikus kosmikus added this to the 0.2.5.0 milestone Apr 13, 2017
@kosmikus
Copy link
Member

@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.

@UnkindPartition
Copy link
Contributor Author

Yes, now the code is much simpler. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants