Skip to content

Generic n-ary programs (zipWith, alignWith, lift, etc.) #10

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

Closed
mechvel opened this issue Feb 28, 2014 · 8 comments
Closed

Generic n-ary programs (zipWith, alignWith, lift, etc.) #10

mechvel opened this issue Feb 28, 2014 · 8 comments

Comments

@mechvel
Copy link
Contributor

mechvel commented Feb 28, 2014

I wonder of wherher the library needs some generalized zipWith-n functions.
For example, the below function is actually zipWith3,
but one list is by List and others are by List.All:

   zip3with? : (triples : List (C × ℕ × C))    All.All ^eq triples  
                    All.All (\e  e > 0) $ map tuple32 triples    List Item 
    zip3with? [] _ _  =  []
    zip3with? ((p , e , d) ∷ triples) (d=p^e ∷a eqs) (e>0 ∷a restExps>0) =
                                                      item ∷ (zip3with? triples eqs restExps>0)
                                                     where
                                                     item = record{ ... } 
@MatthewDaggitt
Copy link
Contributor

So off the top of my head I'm struggling to come up with a generalised zipWith-n function which is both sufficiently general and easy to reason about. Do you have such an implementation?

I don't think zip3with is common or useful enough to warrant being included in the standard library.

@MatthewDaggitt
Copy link
Contributor

Closing as I'm afraid I can't come up with a suitable zipWith-n function.

@gallais
Copy link
Member

gallais commented May 15, 2019

I think this ought to be doable using the code in #608

Edit: yep. uncurried version (_<$>_ is map over Sets using a level polymorphic endofunctor on Set l):

zw-aux :  n {ls} {as : Sets n ls} 
         (Product n as  R) 
         (Product n (List <$> as)  List R)
zw-aux 0       f as         = []
zw-aux 1       f (as , _)   = map (f ∘ (_, tt)) as
zw-aux (suc n) f (as , ass) = zipWith _$_ fs as
  where fs = zw-aux n (flip (curry f)) ass

@gallais gallais self-assigned this May 15, 2019
@gallais gallais added this to the v1.1 milestone May 16, 2019
@jespercockx
Copy link
Member

How about

open import Level using (Level)
open import Function
open import Function.Nary.NonDependent
open import Data.Nat
open import Data.Product using (_×_; _,_; proj₁; proj₂) renaming (curry to curry₂; uncurry to uncurry₂)
open import Data.List using (List; []; _∷_; map) renaming (zipWith to zipWith₂)

variable
  l : Level
  R : Set l

zipWith :  n {ls} {as : Sets n ls} 
          Arrows n as R  Arrows n (List <$> as) (List R)
zipWith zero f = []
zipWith (suc zero) f = map f
zipWith (suc (suc n)) f xs₀ xs₁ = zipWith (suc n) id (zipWith₂ f xs₀ xs₁)

or alternatively

zipWith :  n {ls} {as : Sets n ls} 
          Arrows n as R  Arrows n (List <$> as) (List R)
zipWith zero f = []
zipWith (suc zero) f = map f
zipWith (suc (suc n)) f xs₀ xs₁ = zipWith (suc n) (uncurry₂ f) (zipWith₂ _,_ xs₀ xs₁)

@gallais
Copy link
Member

gallais commented May 31, 2019

I like the second one better. I am puzzled because I tried my best and I really
could not see how to implement it.

@MatthewDaggitt
Copy link
Contributor

Going to remove the v1.1 milestone for this as I don't think it's urgent.

@MatthewDaggitt MatthewDaggitt removed this from the v1.1 milestone Jun 15, 2019
@gallais
Copy link
Member

gallais commented Jun 26, 2019

Generic n-ary lift for applicatives following a discussion with @Zambonifofex

open import Category.Applicative using (RawApplicative) hiding (module RawApplicative)

module _ (Test :  {ℓ}  Set Set ℓ)
         (raw-applicative :  RawApplicative (Test {ℓ})) where

open import Data.Unit
open import Level using (_⊔_; Lift)
open import Data.Nat.Base
open import Data.Product
open import Data.Product.Nary.NonDependent
open import Function
open import Function.Nary.NonDependent

module App {ℓ} = Category.Applicative.RawApplicative (raw-applicative ℓ)

Productκ :  n {l} (as : Sets n (lreplicate n l))  Set l
Productκ zero    as       = Lift _ ⊤
Productκ (suc n) (a , as) = a × Productκ n as

toProductκ :  n {l} {as : Sets n (lreplicate n l)}  Product⊤ n as  Productκ n as
toProductκ zero    _        = _
toProductκ (suc n) (v , vs) = v , toProductκ n vs

fromProductκ :  n {l} {as : Sets n (lreplicate n l)}  Productκ n as  Product⊤ n as
fromProductκ zero    _        = _
fromProductκ (suc n) (v , vs) = v , fromProductκ n vs

curryκₙ :  n {l} {as : Sets n (lreplicate n l)} {r} {b : Set r} 
          (Productκ n as  b)  as ⇉ b
curryκₙ n f = curry⊤ₙ n (f ∘ toProductκ n)

uncurryκₙ :  n {l} {as : Sets n (lreplicate n l)} {r} {b : Set r} 
            as ⇉ b  (Productκ n as  b)
uncurryκₙ n f = uncurry⊤ₙ n f ∘ fromProductκ n


sequenceA :  n {l} {as : Sets n (lreplicate n l)} 
            Productκ n (Test <$> as)  Test (Productκ n as)
sequenceA zero    p        = App.pure p
sequenceA (suc n) (ta , p) = _,_ App.<$> ta App.⊛ sequenceA n p

lift :  n {l} {R : Set l} {As : Sets n (lreplicate n l)} 
       As ⇉ R  (Test <$> As) ⇉ Test R
lift n f = curryκₙ n (λ ps  uncurryκₙ n f App.<$> sequenceA n ps)

@gallais gallais changed the title generic zipWith-n Generic n-ary programs (zipWith, alignWith, lift, etc.) Jun 26, 2019
gallais added a commit to gallais/agda-stdlib that referenced this issue Sep 30, 2022
@MatthewDaggitt
Copy link
Contributor

Fixed by 58462cf. Congrats to @gallais for fixing by far the oldest issue in the library!

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

No branches or pull requests

4 participants