Sent from my iPad
On Dec 13, 2017, at 11:13 PM, Stephen Celis <stephen.ce...@gmail.com> wrote: >> On Dec 13, 2017, at 9:53 PM, Erica Sadun <er...@ericasadun.com> wrote: >> >> Chris L had a beautiful solution for an "Unwrappable" protocol that allowed >> all of the optional sugar to be extended to any type that had a biased >> `Wrapped` item, allowing it to be used with `Either`, `Wrapped`, etc as well >> as form the basis for `Optional` itself. >> >> protocol Unwrappable { >> associatedtype Element >> func unwrap() -> Element? >> } > > It would definitely be nice to make "Optional" sugar work for non-"Optional" > types! (I think the goal for "async"/"await" is to make it work for any > continuation, so it's basically Haskell "do" notation for Swift!) > > I'm not sure the "Unwrappable" protocol can handle many of the examples I > mentioned (accumulative errors, parallelism), though I wonder if it could be > designed differently to do so. The applicative structure requires just 2 > functions[1]: > > protocol Applicative<A>: Functor<A> { > static func pure(_ value: A) -> Self > static func <*> <B>(lhs: Self<(A) -> B>, rhs: Self) -> Self<B> > } > > Such a protocol isn't possible in Swift (yet), Thanks for jumping in and elaborating on a more general approach! I don’t want to sidetrack the thread, but it actually is possible to encode higher-kindred types and protocols requiring them in Swift today. It’s a bit clunky and requires some boilerplate but the technique is worth knowing. https://gist.github.com/anandabits/f12a77c49fc002cf68a5f1f62a0ac9c4 Some Kotlin folks have created a pretty robust FP library using the same technique: http://kategory.io/. > but it could unlock this kind of sugar for everyone. Here's "Optional" > conformance: > > extension Optional: Applicative<Wrapped> { > static func pure(_ value: Wrapped) -> Wrapped? { > return value // promoted to Optional.some > } > > static func <*> <B>(lhs: Optional<(Wrapped) -> B>, rhs: Optional) -> B? { > guard let lhs = lhs, rhs = rhs else { return nil } > return lhs(rhs) > } > } > > We can't conform to such an "Applicative" protocol today, but we _can_ still > write and use these functions in a concrete manner! (Delete the conformance > and see!) > > The original post in this thread had this example: > > getPostageEstimate(source: String, destination: String, weight: Double) > > If we were dealing with this function in the world of optional arguments, > here's how we could use our abstraction: > > Optional.pure(curry(getPostageEstimate)) <*> john.address <*> > alice.address <*> pure(2.0) > > It's not _too_ bad, though it's kinda noisy, we have to maintain a bunch of > custom code, we have to curry "getPostageEstimate" before passing it through, > we lose our argument labels, and we're living in custom operator world, which > can be disconcerting at first. > > If Swift provided sugar over this structure, we'd merely need to do this: > > getPostageEstimate(|source: john.address, destination: alice.address, > weight: 2.0|) > > What's even neater is we can use this same format for types that wrap values > in other ways! Let's say the addresses are coming from untrusted sources and > need to be validated: > > getPostageEstimate(|source: try validateAddr(john), destination: try > validateAddr(alice), weight: 2.0|) > > If both addresses are invalid and "throw", we could get both errors and > render them at once to our end user. > > Another example: what if we want to get the postage estimate for two > addresses that we need to fetch asynchronously: > > getPostageEstimate(|source: await myAddress(), destination: await > theirAddress(), weight: 2.0|) > > Such a syntax allows those requests to run in parallel and not block :) > > In these examples, "Optional" promotion becomes applicative promotion ("2.0" > is getting wrapped automatically), which might open a can of worms but it's a > fun can to think about! > > > -- > [1]: Well, technically it also requires "map", since any applicative is a > functor, and it also requires that it follows some math laws. > > > Stephen
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution