Pulling an applicative/apply out of a record

Quick question for the experts out there. I need to process some records. The records come in in an unordered stream of record fields. From each stream of fields I want to produce a Record entry containing the fields I need to do my calculation.
data Record = { field1 :: Type1, field2 :: Type2, ... }
I was thinking this setup might work nice with something like
data RecordF d = RecordF { field1 :: f Type1, field2 :: f Type2, ... }
as I could then have (1) a monoid version I could accumulate use as an accumulator over the stream
type RecordM = RecordF []
and (2) a final version.
type Record = RecordF Identity
This final version seems like it should easily come from the later by pulling the [] (or anything else that has the Apply/Applicative structure) to the outside and then taking the head of the resulting list. While I could write the boilerplate to do this, it seems like something I should be able to do more elegantly. The best I have come up with so far is to use the lens package to give me an isomorphism to a tuple. Then I need a uncurried zip for arbitrarily large tuples. Follow this by an isomorphism back. RecordF (f Type1) (f Type2) ... -> (f Type1, f Type2, ....) -> f (Type1, Type2, ...) -> f (Record Type1 Type2 ...) I can't seem to find any uncurried zip implementations for arbitrarily large tuples (or any other way to do this without writing the boilerplate). Am I missing something? Is there a better way to do this? Thanks! -Tyson PS: It seems the Data.Vinyl package has something along these lines with the rtraverse function https://hackage.haskell.org/package/vinyl-0.5.1/docs/Data-Vinyl-Core.html

On Sun, Feb 07, 2016 at 02:25:41AM -0500, Tyson Whitehead wrote:
RecordF (f Type1) (f Type2) ... -> (f Type1, f Type2, ....) -> f (Type1, Type2, ...) -> f (Record Type1 Type2 ...)
I can't seem to find any uncurried zip implementations for arbitrarily large tuples (or any other way to do this without writing the boilerplate). Am I missing something? Is there a better way to do this?
I would call this a multi-typed 'Data.Traversable.sequence'. Data.Profunctor.Product.TH generates this (in fact something slightly more general that works for ProductProfunctors, not just Applicatives). Currently it only works for fully polymorphic record types, but we could tweak it so it so it's a bit more general. Tom

On Sunday, 7 February 2016 05:17:55 UTC-5, Tom Ellis wrote:
RecordF (f Type1) (f Type2) ... -> (f Type1, f Type2, ....) -> f (Type1, Type2, ...) -> f (Record Type1 Type2 ...)
I can't seem to find any uncurried zip implementations for arbitrarily large tuples (or any other way to do this without writing the boilerplate). Am I missing something? Is there a better way to do
On Sun, Feb 07, 2016 at 02:25:41AM -0500, Tyson Whitehead wrote: this?
I would call this a multi-typed 'Data.Traversable.sequence'.
Data.Profunctor.Product.TH generates this (in fact something slightly more general that works for ProductProfunctors, not just Applicatives).
Thanks for the pointer Tom. Currently reading up about it. Found your post too. http://h2.jaguarpaw.co.uk/posts/product-profunctor-folds/ Cheers! -Tyson

On Sun, Feb 7, 2016 at 2:25 AM, Tyson Whitehead
Quick question for the experts out there.
I need to process some records. The records come in in an unordered stream of record fields. From each stream of fields I want to produce a Record entry containing the fields I need to do my calculation.
data Record = { field1 :: Type1, field2 :: Type2, ... }
I was thinking this setup might work nice with something like
data RecordF d = RecordF { field1 :: f Type1, field2 :: f Type2, ... }
as I could then have (1) a monoid version I could accumulate use as an accumulator over the stream
type RecordM = RecordF []
and (2) a final version.
type Record = RecordF Identity
This final version seems like it should easily come from the later by pulling the [] (or anything else that has the Apply/Applicative structure) to the outside and then taking the head of the resulting list.
While I could write the boilerplate to do this, it seems like something I should be able to do more elegantly. The best I have come up with so far is to use the lens package to give me an isomorphism to a tuple. Then I need a uncurried zip for arbitrarily large tuples. Follow this by an isomorphism back.
RecordF (f Type1) (f Type2) ... -> (f Type1, f Type2, ....) -> f (Type1, Type2, ...) -> f (Record Type1 Type2 ...)
I can't seem to find any uncurried zip implementations for arbitrarily large tuples (or any other way to do this without writing the boilerplate). Am I missing something? Is there a better way to do this?
Thanks! -Tyson
PS: It seems the Data.Vinyl package has something along these lines with the rtraverse function
https://hackage.haskell.org/package/vinyl-0.5.1/docs/Data-Vinyl-Core.html _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
https://gist.github.com/aavogt/f7d875abaf504dc3bf12 shows how you can do it with extensible, HList, and vinyl. Or if you want to stick with your current way of defining records, I think https://wiki.haskell.org/Template_Haskell#.27generic.27_zipWith could work too. Regards, Adam
participants (3)
-
adam vogt
-
Tom Ellis
-
Tyson Whitehead