I finished reading an article about why Haskell was their first-choice development language and I came to this nice list of
reasons:
- Haskell has a strong static type system that prevents errors and reduces cognitive load
- Haskell enables writing code that is composable, testable, and has predictable side-effects
- Haskell facilitates rapid development, worry-free refactoring, and excellent maintainability
- Haskell programs have stellar performance, leading to faster applications and lower hardware costs
- Haskell is great for domain modeling and preventing errors in domain logic
- Haskell has a large number of mature, high-quality libraries
- Haskell makes it easy to write concurrent programs
- Haskell enables domain-specific languages, which foster expressiveness and reduce boilerplate
- Haskell has a large community filled with smart and friendly people
and I thought “Huh”.
Swift is true for all of these points.
And then I thought “Well, Swift is an acceptable Haskell”.
The article starts out by showing how higher order functions make things great in Haskell. Swift has those, too.
func squareMe(_ x: Int) -> Int {
return x * x
}
let source = [1, 2, 3, 4, 5]
source.map { squareMe($0) } // returns [1, 4, 9, 16, 25]
This code is composable and reusable. Nice.
A little later there is some discussion of Abstract Data Types. The provided example is strange (to me) because it uses Integer Dollars. I think we can do better (and not just because it’s Swift).
import Foundation
protocol Currency {}
struct Dollars: Currency {
let whole: Int
let cents: Int8? // valid only between 0 and 100
init(whole: Int, cents: Int8 = 0) {
self.cents = (0..<100).contains(cents) ? cents : nil
self.whole = whole
}
}
enum InvoiceStatus {
case Issued, Paid, Canceled
}
struct CustomerInvoice {
let invoiceNumber: Int
let amountDue: Currency
let tax: Currency
let billableItems: [String]
let status: InvoiceStatus
let createdAt: Date
let dueDate: Date
}
We can then write functions on these data types. In the article there is a nice example of Haskell case statement. Swift has those, too.
func createCustomerNotification(_ invoice: CustomerInvoice) -> String {
switch invoice.status {
case .Issued:
return "New invoice # \(invoice.invoiceNumber) due on \(invoice.dueDate)"
case .Paid:
return "Successfully paid invoice # \(invoice.invoiceNumber)"
case .Canceled:
return "Invoice # \(invoice.invoiceNumber) has been cancelled"
}
}
Swift, like Haskell, requires case statements to be exhaustive. If we update the InvoiceStatus enum to include a new status Refunded the code will show a compile error and prompt us to fix the swtich cases.
I'm not translating all the examples from the article, mostly because if you want Abstract Data Types and higher order functions you can have them in Swift.
- Swift has a strong static type system that prevents errors and reduces cognitive load
- Swift enables writing code that is composable, testable, and has predictable side-effects
- Swift facilitates rapid development, worry-free refactoring, and excellent maintainability
- Swift programs have stellar performance, leading to faster applications and lower hardware costs
- Swift is great for domain modeling and preventing errors in domain logic
- Swift has a large number of mature, high-quality libraries
- Swift makes it easy to write concurrent programs
- Swift enables domain-specific languages, which foster expressiveness and reduce boilerplate
- Swift has a large community filled with smart and friendly people