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