Fork me on GitHub
#off-topic
<
2022-09-30
>
Ben Lieberman17:09:48

generic FP question: is the behavior of map (working on multiple collections) an example of lifting?

hiredman19:09:30

I think it is more of a generalization of maps definition to also include zipping. Lifting is usually used to turn a function that operates on a value into a function that operates on a value in some context (like a monad or a functor)

๐Ÿ‘Œ 1
skylize21:09:00

Yes. See https://wiki.haskell.org/Lifting > If you look at the type of fmap (`Functor f =&gt; (a -&gt; b) -&gt; (f a -&gt; f b)`), you will notice that fmap already is a lifting operation: It transforms a function between simple types a and b into a function between [functors]ยน of these types. > ยน Original text uses "pairs" here, as the specific type under discussion, but applies equally to other functors. Clojure's map is equivalent to Haskell's fmap, implemented for seqable containers.

didibus22:10:08

Ya, you can think of it as, normally the function you pass to map doesn't work with collections like say a vector:

(inc [1 2 3])
That doesn't work. But you can lift inc so it can also be used on a vector by using map
(map inc [1 2 3])
Now you were able to use inc over a vector without changing inc , so it was lifted from a function of a -> a to a function of [a] -> [a] What you can't do in Clojure with map is extend map to work with other contexts besides seqables.

skylize02:10:46

Couldn't you "extend map" by implementing an ISeq with next and more both as no-ops, and cons silently failing to attach any new values? ๐Ÿ˜ˆ

didibus17:10:16

That would just create new collections, well, seqs , which would work with map, but map will still return a sequence, and not the type of your container. To do that, you don't need to implement ISeq, you only need to implement a seq function for your type, which is much simpler.

didibus17:10:27

So in that sense, map only works within the context of sequences, because it always returns a sequence.

didibus17:10:47

So with regards to category-fp, map is not the same as fmap, because it doesn't apply to all Functors, it only applies to sequences, allowing to apply a function to elements of sequences preserving the structure of sequences, but it won't apply to other Functors and preserve their structure. If you make your other Functors also a sequence, map will remove your other structure and return only something that is a sequence.

didibus17:10:05

I'm not too sure how lists work in Haskell, but I feel in that sense Clojure's map is probably more like Haskell's map except Haskell's List becomes Clojure's Sequence

skylize19:10:13

> but map will still return a sequence, and not the type of your container > Good point. Definitely frustrating that having sequence functions for everything comes at the cost of everything being transformed into a generic sequence. > except Haskell's List becomes Clojure's Sequence > That's about right. You do have to squint a little though, since you can't get a proper sequence without some other seqable as intermediate, and the structure of that intermediate seqable is lost in the process.

didibus19:10:30

You can get a sequence directly using cons , and list is a sequence as well.

skylize20:10:45

> with regards to category-fp, map is not the same as fmap, because it doesn't apply to all Functors > There is nothing in Category Theory that states, or even vaguely implies, that you must have a singular function that is somehow able to describe functorial morphisms between all possible categories. Even in Haskell new types do not automatically conform to fmap, just because you claim it is a functor. You must define fmap for a specific type before you can use it, or define other aspects of the type which can be used to infer how fmap should behave. Haskell just provides a statically verifiable way to describe mapping over many different types, and prebuilt implementations for more types than just lists.

didibus21:10:47

I meant Clojure's map. Generally category theory inspired functional programming languages have a generic mapping function for all functors. And in general, category theory is useful specifically with regards to being able to implement very generic operations. Clojure's map is concrete to sequences, not generic to all functors. Functor itself is not first-class in Clojure either, like there's not a real functor construct, it just happens that sequences follow the same design pattern.

didibus21:10:26

So like, if you're comparing Clojure's map with Haskell's fmap or Scala's map, its different in that Clojure's version is not generic, but specific to sequences.

skylize21:10:00

I don't know anything about Scala. But Haskell's fmap is not "generic". It is polymorphic. A type cannot be mapped over with fmap without a corresponding implementation that can be dispatched to for that type.

didibus21:10:12

parametric polymorphism == generic, in my sentence

skylize21:10:35

You will find Haskell emulation libraries in almost every common language, because you can build your own polymorphic dispatch in any language. The difference is that with Haskell the compiler will help you, and the language has constructs designed around the theory.

didibus21:10:24

> Parametrically polymorphic functions and data types are sometimes called generic functions and generic datatypes, respectively, and they form the basis of https://en.wikipedia.org/wiki/Generic_programming. from https://en.wikipedia.org/wiki/Parametric_polymorphism

didibus21:10:58

I think Haskell might also call something else generic, I don't really know much about that, and that wasn't was I was referring too

didibus21:10:35

If it is more clear to you: So like, if you're comparing Clojure's map with Haskell's fmap or Scala's map, its different in that Clojure's version is not polymorphic on its parameters' types, but specific to sequences.

skylize21:10:13

We were using different definitions of generic. ๐ŸŒ

skylize21:10:36

But really all I was arguing against was this. > with regards to category-fp, map is not the same as fmap, because it doesn't apply to all Functors > Haskell's polymorphism is not equal to the category theory backing functors and monads.

didibus21:10:09

Ya, when I said "category-fp" I meant category theory inspired programming languages. to distinguish from the more scheme inspired ones where it's more about higher order functions and closures than anything else. None of those languages are exactly same as category theory, you can only vaguely derive constructs and patterns inspired by category theory when used in the context of a programming language I feel.

๐Ÿ‘ 1
didibus21:10:35

So like, map and sequences can be fitted in the theory of Functors, but the Clojure map doesn't directly reference Functors or is modeled the way other FP languages that mention explicitly Functors tend to do so.

didibus21:10:45

> We were using different definitions of generic. ๐ŸŒ Ya, I've found between languages, it gets pretty confusing because same words are often reused with subtle different meaning. I feel this is more true in FP concepts for some reason.

skylize22:10:57

> Ya, when I said "category-fp" I meant category theory inspired programming languages. > Theoretical vs programming constructs are also always getting entangled when talking fp. It's great to have Haskell's direct implementation to point to for understanding. But it is just one of many possible interpretations of how to reify the theories.

๐Ÿ’ฏ 1