5 ms·
Quote: "I don't think you can do anything like this with Python or any other practitioner's language that I'm familiar with" So, then you're not familiar with
by unnouinceput 7y ago
Quote: "I don't think you can do anything like this with Python or any other practitioner's language that I'm familiar with"
So, then you're not familiar with C/C++, Java, C#, Pascal/Delphi, Ada - to say the least.
- rgoulter 7y agoWhat's the equivalent of -- zs' = [Just 2, Nothing, Just 4] zs' = (fmap . fmap) (+1) [Just 1, Nothing, Just 3] in C?
- FeepingCreature 7y agoAt least on the D side: Nullable!int[] zs = [2.nullable, Nullable!int(), 4.nullable]; // no partial application, and // separate template parameters and runtime parameters // so (fmap . fmap) (+1) is one function Nullable!int[] zs2 = map!(apply!(i => i + 1))(zs).array; The C version probably has a lot more function pointers, and may use nonstandard compiler functions like closures. But in principle you could do the same thing.
- sweeneyrod 7y agoThat's not the same, it's just composing the maps for arrays and nullables. The whole point of fmap is that you can write (fmap . fmap) (+1) [Just 1, Nothing, Just 3] but also (fmap . fmap) (+1) Just [1, 3], rather than using (list_map . option_map) (+1) and (option_map . list_map) (+1) respectively. The usefulness of this is arguable. In my biased opinion as someone who favours OCaml (which lacks the typeclasses that allow this) over Haskell, I think it's minimal. While it's definitely useful to recognise that lists, options and promises are examples of the same pattern, I don't this generalisation has many benefits in code (at least in MLs where you don't need this pattern just to print things).
- FeepingCreature 7y ago> The usefulness of this is arguable. And I have argued it on D, and we very deliberately did not go with the range semantics. Optional types are not ranges unless you're compulsively hunting for forced commonality. Might as well treat any value as a range of 1.
- feanaro 7y agoThey are not ranges, but they are functors, as are ranges. The commonality between ranges and option types is that they are both functors and this is not forced.
- FeepingCreature 7y agoI guess I subscribe to the school of thought that says that types are supposed to model the domain information of the data they represent. I know what it means when a value is either provided or not provided. I know what it means when a field has one of a number of values. I don't know what it's supposed to represent, in a domain sense, when a value is "a functor."
- feanaro 7y agoNote that a value is not a functor, its type is. When some type T is a functor, this means that T contains (as part of its definition) a type variable which you can change by mapping functions over values of type T. For instance, the list type `[a]` and the option type `Maybe a` are both functors. The associated type variable is `a`. This type variable can be manipulated by using `map` to apply some function `f : a -> b` over values of both `[a]` and `Maybe a`. Applying `f` using `map` over such values would yield values of new types, namely `[b]` and `Maybe b`. This implies that `map f` is a general way of expressing the application of function `f` to values of any functor type. The notion of functor types is therefore supposed to represent any kind of abstract containment relationship. In other words, any time you have the situation of an arbitrary type being wrapped in some kind of "wrapper" (list of..., set of..., range of..., optionally present..., etc), you are dealing with a functor type. The functor abstraction allows you to apply ordinary functions to such values in a uniform way, regardless of which particular kind of container or wrapper we are dealing with.
- giornogiovanna 7y agoYes, of course you can encode it in any language you want, but the point is that ML-ish languages make it extremely natural to think like this, and Java makes it impossibly painful. Haskell makes traditional imperative algorithms painful, though, which is arguably a greater loss.
- woadwarrior01 7y agoOf all the languages I've seen, Swift seems to be the best compromise between ML style FP and imperative programming.
- aloisdg 7y agoDid you try F#? How would you rank it?
- woadwarrior01 7y agoUnfortunately, I haven’t. The only ML family languages that I have significant experience with are SML and OCaml.
- sweeneyrod 7y ago> ML-ish languages make it extremely natural to think like this You say that, but actually fmap doesn't exist in OCaml (or I assume any other common MLs). Of course you can embed a language and type system within it that does have it (https://blog.janestreet.com/generic-mapping-and-folding-in-ocaml/ https://blog.janestreet.com/generic-mapping-and-folding-in-o...) but that's different.
- giornogiovanna 7y agoUsing List.map and Option.map is more verbose and less general, but it's still most of the way there. OCaml still has currying, algebraic data types, "implicit" returns, tail call optimization, etc., and it encourages recursion instead of loops wherever applicable.
- goto11 7y agoI guess you can implement fmap in any language with higher-order functions including Python. The point is it is built into Haskell and supported by a number of fundamental types out of the box.
- Silhouette 7y agoSo, then you're not familiar with C/C++, Java, C#, Pascal/Delphi, Ada - to say the least. Well, yes, strictly speaking you can do just about anything in just about any Turing complete language if you work hard enough. However, expressing patterns like that with the powerful, general semantics and the elegant syntax of the Haskell version is not something that is offered by any of the other languages you mentioned. It was perhaps an unfortunate choice of example, because many languages do have first class support for some sort of array/list type and some sort of optional/nullable type and so might offer a reasonably tidy implementation of this specific case. However, in Haskell, the exact same technique would apply just as much to any choices of Functors. Indeed, you can often write generic algorithms that work with any choices of Functors (or Applicatives, Foldables, Monoids, etc, depending on what minimal functionality is required for your algorithm to make sense). Likewise, there are very many generic algorithms already available in libraries that can be used with both the standard instances of those typeclasses and new ones you write yourself. This is the big win for Haskell's type and typeclass system, or what the original author refers to as its emphasis on structure.
- smegma2 7y agoNot sure about the last two you listed, but those languages don't support parametric polymorphism which means that although you can write a `fmap` method for things, the compiler can't check its type properly. At best you can write an interface, but that interface won't be able to guarantee that the functor returned by fmap is the same one you started with.
- hopia 7y agoJava and C# at least should support (parametric) polymorphism via Generics. In Haskell you don't need GHC Generics to achieve parametric polymorphism though, it's used for different things.
- rovolo 7y agoI think they mean type classes/constructors [1] since they're talking about fmap, though I'm not sure what the proper name is for that concept. What name would you use? They're trying to say that Java doesn't support writing a single function like so: <T<A> extends Iterable<A>, A, B> T<B> fmap(T<A> iterable, Function<A,B> mapper) I.e. you can't pass ArrayList<A> to a method which takes List<A> and maps to List<B> and know for certain that you get an ArrayList<B> out. [1] https://en.wikipedia.org/wiki/Type_class#Higher-kinded_polymorphism https://en.wikipedia.org/wiki/Type_class#Higher-kinded_polym...
- hopia 7y agoWell data constructors are a part of algebraic data types which don't really exist in OOP. Unless you consider the class itself (or an interface) or its constructor as the algebraic data type constructor, and its properties/parameters as the values. I'm not so sure fmap would make semantically as much sense in something like Java as it does in FP.