Just a quick follow up to add some clarifications… On Friday, October 17, 2014 7:11:12 AM UTC-4, Daniel James wrote: > > > Hi Michael, > > As I said above, while this is certainly a function that transforms one > reducing function into another, you should not call this a transducer. It > is something else, with a distinct type. > > Compare > > type Transducer a b = forall r . Reducer a r -> Reducer b r > > with > > type SomethingElse a b r = Reducer a r -> Reducer b PersistentMap > > The baggage handler analogy is getting at the idea that you really > shouldn’t have to know anything about the conveyance, the `r` here. The > rank-2 polymorphic type neatly enforces that a valid implementation *can’t* > know. Your function does know, because it has removed the polymorphism and > always reduces on maps—you’ve dictated that you are using map trolleys. >
I’ve been making some simplifications to abstract away from the unnecessary details, but I think I was a bit too loose when I said “it has removed the polymorphism”. Your group-by-xf function has a type the can be characterized as the following: group-by-xf :: (a -> k) -> (forall. Reducer a r -> Reducer a (Map k r)) You are still polymorphic in the type of values that are being reduced, as well as in the type of the values of the map (you are using the input reducing function to construct the values of the map). Nonetheless, it is still remains something other than a legitimate transducer: you have specialized `Reducer a r` to `Reducder a (Map k r)`. And that’s the bit that counts. > > I think you may have missed my point here. > > Your group-by-xf function only makes sense in a specific interpretation of > `transduce`, again indicating that it is not a valid transducer. > > If `into` was changed to reflect my proposal, you would find it would > blown up with your group-by-xf: > > (into [1 2 3] (group-by-xf odd?) (range 100)) > > A map would be returned not a vector! Similarly, if you used it with > `sequence`, you’d get a map, not a sequence; or with core.async channels, > you’d corrupt the channel by replacing its buffer with a map. > > Let me rephrase. As you said in your first reply, `transduce` *already* doesn’t jibe with your `group-by-xf`. - transduce: it doesn’t call your 0-arity, so it will give you `init`, but you require it to be a map. - into: it doesn’t call your 0-arity, so it will give you the `to`, a collection, but you require it to be a map. - sequence: it doesn’t call your 0-arity, so it will give you a lazy sequence, but you require it to be a map. - chan: it doesn’t call your 0-arity, so it will give you a channel buffer, but you require it to be a map. *If*, these were all changed to call your 0-arity: - transduce: you replaced `init` with {}, so the reduction returns a map. - into: you throw away in output collection `to`, and return a map. - sequence: exception??? whatever machinery is handling the laziness will surely not like being handed a map - chan: exception??? whatever machinery is handling the channel will surely not like it when you replace the channel buffer with a map Your function is good for use with `reduce`, but only that. I hope I’ve helped build an intuition for why it’s actually impossible to implement ‘group by’ as a transducer. Dan -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.