Hi everyone, I read every post in the Higher-Kinded Types ( 
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151214/002736.html
 
<https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151214/002736.html>
 ) thread from about a year ago, and I was wondering what's the status on the 
matter: I'm aware of the proposal draft ( 
https://github.com/typelift/swift/issues/1 
<https://github.com/typelift/swift/issues/1> ), but I'd like to know if the 
Swift team has reconsidered the possible relevance of HKT for Swift in the 
foreseeable future.

By reading the discussion I found that the main concern from the Swift team was 
about practical use cases that could be of interest for a huge chunk of Swift 
developers: I don't think that a language feature should be there only if 
affects the majority of users, because of course you always have users at many 
different levels of awareness and understanding, not to mention experience and 
background, but I understand that, considering the time constraints in language 
development and proposals review, the focus should (initially) be on things 
that matter the most to the vast majority of developers.

But the idea of opposing a proposal because it's "hard to understand" (to some 
people, with different background) is baffling to me: there could be NO 
evolution whatsoever if everyone's only focus was on what feels familiar. But I 
don't want to talk about this: I just want to mention that if someone argues 
that they're not understanding a construct even if they consider themselves 
smart and experienced, that's their problem (maybe they're simply non 
experienced in that particular field), not a problem of the construct itself. 
And the fact that most things are mappable is not something functional 
programmers "believe": there's a huge corpus of research in the field of 
abstract mathematics that confirms this intuition. But anyway, let's move on.

I'd like to mention something that I consider a practical use case for the need 
of being able to express something like mappables and flatMappables in a 
abstract way: what's usually referred to as "monad transformers". I know that 
it's another concept that can be hard to grasp if you're not used to work with 
monads, but bear with me. Also, not sure about the etiquette here: it's an old 
discussion, but I wanted to offer my two cents.

Many functional programming techniques try to achieve true composability of 
code by decomposing logic in generic classes, that express a particular piece 
of that logic: the "Result" type  ( https://github.com/antitypical/Result 
<https://github.com/antitypical/Result> ) is a classic case (the same concept 
is similarly implemented by Swift throwable functions, but in a less composable 
way). There are many more types that do this, for example the Deferred type ( 
https://github.com/bignerdranch/Deferred 
<https://github.com/bignerdranch/Deferred> ) was also mentioned in the 
discussion. Another type that I use a lot is the Writer type ( 
https://en.wikipedia.org/wiki/Monad_(functional_programming)#Writer_monad 
<https://en.wikipedia.org/wiki/Monad_(functional_programming)#Writer_monad> ) 
that lets me accumulate an auxiliary result while executing an algorithm ( for 
example, generating an index path while traversing a tree ). And the Optional 
type is already in Swift. But while these types are useful by themselves, they 
become even more powerful when combined: for example, Deferred + Result is 
basically a Future, that is, an asynchronous computation that can fail. Even 
more interesting is a Deferred + Writer + Result (I going to refer to it as 
"DefWriRes"), something that I currently use while developing my HTTP clients, 
because I can accumulate information about request and response in a clean, 
composable way: unfortunately, mapping and flatMapping breaks when combining 
these types, because mapping a DefWriRes will require a function working on 
Writer, while I really just work on the type wrapped by the internal Result. 
Monad transformers work that way: they allow you to "go deeper" in combined 
monads. Now, the interesting thing is that to map a DefWriRes we only need to 
now that Deferred, Writer and Result are mappable, but without this abstraction 
I'm forced to copy and paste hundreds of lines of code (for every possible 
combination) where the only thing that changes is the type definition, because 
the method calls are just maps.

The case is similar for flatMap, so I need to call "flatMap" on something 
that's flatMappable, with the difference that I need to be able to unwrap the 
value in the Result (so I need to know how Result works, it's not just 
mapping), and I need to be able to create a "empty" Writer and Deferred (that's 
already achievable by the type system). But the case is similar, the only 
difference is that I need a specific "ResultTransformer" (I actually 
implemented this via protocols and constrained extensions, but the 
implementation details are not relevant for the case).

So what's the use case? If I was able to generically express a mappable and a 
flatMappable, I could combine those things multiple times at any level without 
rewriting the same almost identical code for every combination. And even if 
you're not a functional programmer, types like these are very useful to clearly 
and cleanly express the semantics of your code: in fact, the Optional type is 
extremely useful exactly for this, and I'm thankful for the fact that it is in 
the standard library, along with the respective map and flatMap methods.

What do you think? Thanks


Elviro
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to