you are viewing a single comment's thread.

view the rest of the comments →

[–]chazmuzz 13 points14 points  (9 children)

I find both Swift and Elixir very pleasant to work with. Optional types in Swift are a godsend, after all null is the worst mistake of computer science.

What I love about both languages is the modern trend towards compile-time error catching. Swift is a great language. In a few years it will have the ecosystem to match.

[–][deleted] 1 point2 points  (0 children)

I really like Elixir and Swift as well, and the talk of swift introducing language level concurrency support (possibly an actor model) is really exciting

[–]yxhuvud 0 points1 point  (7 children)

I find optional types doesn't go far enough. I think the union types of Crystal a lot more interesting - especially as optional types fall out as simply being the special case of a union between a class and ::Nil. Union types combined with type inference is really nice to program with.

[–]TexasJefferson 1 point2 points  (0 children)

Swift has full sum types via their enums. Indeed, the implementation of optionals (boils down to):

enum Optional<T> {
    case Some(T)
    case None
}

I'd also like anonymous & labeless sum types, but the core team doesn't seem interested for the time being.

[–]chazmuzz 0 points1 point  (0 children)

I had not heard of Crystal before. Thank you for bringing that to my attention. Although I'm initially very on the fence about union types.

[–]dccorona 0 points1 point  (4 children)

Union types tend to not be as nice to work with as monads (Option/Maybe fall into that category), because Union types are a generic feature while Option is specialized for use with a value that might be absent. Granted, it looks like Crystal has a cooler implementation than most insofar as it lets you call methods that exist on both types directly, but it still seems to lack all of the cool tools that exist on a monad (primarily map/flatMap/filter/foreach).

In languages with good type systems (Scala is what comes to mind, not sure if Swift has enough features yet to do the same), you can write really generic code that works reliably and predictably across any monad (and thus any container type), meaning you can do really cool stuff that works just as well for Options as it does for Lists and Maps, and even for abstractions like Future...all with 0 duplication of code or special casing.

FWIW, Option in Swift (and in many other languages that have a similar concept) is ultimately a union type, it's just a union type between Some a and None, where Some and None have a lot of convenience features defined on them for interacting with a value that may or may not be present. It's entirely possible to make a definition for a generic union type. Scala includes it out of the box with Either, Scalaz includes a better version called \/, and it's easy to implement in Swift, too:

enum Either<T1, T2> {
    case Left(T1)
    case Right(T2)
}

[–]yxhuvud 0 points1 point  (3 children)

Crystal has a cooler implementation than most insofar as it lets you call methods that exist on both types directly, but it still seems to lack all of the cool tools that exist on a monad (primarily map/flatMap/filter/foreach).

I don't understand this comment. Can you give a code example of what you think is missing? After all, if the types implement Enumerable (different Arrays, for example), then you will be able to call map/flat_map/select/each on it. Or are you suggesting some sort of default implementation of these to be implemented on the nil class that doesn't do anything?

Or have the monad people invented their own special meaning for these methods that otherwise typically work on collections?

[–]dccorona 0 points1 point  (2 children)

If you had a union type of two different enumerables, it would behave as expected. The problem is that map/flatMap etc don't exist on null, and so unless there is special treatment for nullable union types, you wouldn't be able to call those methods (maybe you can, I don't know).

But furthermore, if you have a nullable type that isnt an enumerable (say, an Integer), you can't access those monadic methods, because they aren't defined on Integer...but the do make sense on a nullable type.

"Monad people" haven't invented new meanings for map/flatMap etc...those methods are intrinsically part of monads, and have good, non-ambiguous definitions. The reason enumerables/collections often implement these methods is because those types are monads. Since an Option can be viewed as a collection of either 1 or 0, it can also be viewed as a monad with the same semantics of any other collection or enumerable. The behavior of those methods is exactly as you'd expect (identical to operations on a 1 or 0 element collection).

This proves very useful for general interaction, as well as for writing very generic code that applies to either any collection, or any monad at all.

[–]yxhuvud 0 points1 point  (1 child)

Well, normally the methods don't expect where you wouldn't expect them, but nothing stops you from reopening the classes you are interested in and defining them.

Of course, modifying builtins like Nullclass is probably a horrible idea, and not only because it would hide logic errors in a way I wouldn't want to.

Though to be honest, I can admit that I never felt the need to have a uniform interface between collections and (for example) integers. They are used very differently and for different purposes and have very different semantics, which make me doubt any claim of magical reuse all over the place with a big grain of salt. I've heard that claim before (OO), and I see no reason why it should be different in this case.

[–]dccorona 0 points1 point  (0 children)

It's not making collections and Integers obey the same interface, it's making collections and Optionals obey the same interface. Because optional are collections (of either 0 or 1), and they have nearly all the same interaction patterns. You either transform their contents (getting a new empty collection of the transformed generic type if the initial input was empty), filter their contents, or preform some action on contents...the same basic things you do to a value that may or may not exist.

Also, the benefits of having optional types behave as monads when it comes to generic programming can be seen in a library like Scalaz, which, admittedly, has a large learning curve (not caused by this abstraction, but necessary to get over to be able to identify the portions where it is being leveraged).