Upload
hackraft
View
688
Download
0
Embed Size (px)
Citation preview
Functional Programming
• Higher-order functions
• Immutable states & pure functions
• Modularity
• Types
First Class Functionsfunc add(x: Int) -> Int -> Int { return { y in y + x } }
let addOne = add(1) addOne(2)
// 3
First Class Functionsfunc addTwo(x: Int) -> Int { return x + 2 }
(1...5).map(addTwo)
// [3, 4, 5, 6, 7]
Curryingfunc add(a: Int)(b: Int) -> Int { return a + b }
let addOne = add(1) let xs = 1...5 xs.map(addOne)
// [2, 3, 4, 5, 6]
Generics
func printEach<T: SequenceType>(items: T) { for item in items { print(item) } }
printEach(1...5) printEach(["one", "two", "three"])
Type Inference
let xs = [1, 5, 2, 4, 3] let ys = xs.sorted(<) print(xs) // [1, 5, 2, 4, 3] print(ys) // [1, 2, 3, 4, 5]
Type Inference
let xs = [1, 5, 2, 4, 3] let ys = xs.sorted(<) print(xs) // [1, 5, 2, 4, 3] print(ys) // [1, 2, 3, 4, 5]
Enumerationsenum Fruit: String { case Apple = "apple" case Banana = "banana" case Cherry = "cherry" }
Fruit.Apple.rawValue // "apple"
Enumerationsenum MyApi { case xAuth(String, String) case GetUser(Int) } extension MyApi: MoyaTarget { var baseURL: NSURL { return NSURL(string: "")! }
var path: String { switch self { case .xAuth: return "/authorise" case .GetUser(let id): return "/user/\(id)" } } }
https://github.com/Moya/Moya
Optional Chainingstruct Dog { var name: String } struct Person { var dog: Dog? }
let dog = Dog(name: "Dodge") let person = Person(dog: dog) let dogName = person.dog?.name
Optional Chainingstruct Dog { var name: String } struct Person { var dog: Dog? }
let dog = Dog(name: "Dodge") let person = Person(dog: dog) let dogName = person.dog?.name
Optional Chaining
Functors
let y = Optional(2) y + 3
// Error! // Value of optional type // Optional<Int> not unwrapped
Functorsfunc map<U>(f: T -> U) -> U? { switch self { case .Some(let x): return f(x) case .None: return .None } }
Functors
infix operator <^> { associativity left
}
func <^><T, U>(f: T -> U, a: T?) -> U? { return a.map(f) }
Functors
func <^><T, U>(f: T -> U, a: T?) -> U? { return a.map(f) }
let addOne = { $0 + 1 }
addOne <^> Optional(2) // Optional(3)
Applicativefunc apply<U>(f: (T -> U)?) -> U? { switch f { case .Some(let someF): return self.map(someF) case .None: return .None } }
Applicatives
infix operator <*> { associativity left }
func <*><T, U>(f: (T -> U)?, a: T?) -> U? { return a.apply(f) }
Applicatives
infix operator <*> { associativity left }
func <*><T, U>(f: (T -> U)?, a: T?) -> U? { return a.apply(f) }
func add(a: Int)(b: Int) -> Int { return a + b }
Applicatives
add <^> Optional(2) <*> Optional(3) // Optional(5)
let a = add <^> Optional(2)
let a: (b: Int) -> Int?
Monadstypealias T = Double let f: T -> T = { $0 * 2.0 } let g: (T, T) -> T = { $0 / $1 }
f(g(4, 2))
g: (T, T) -> T?
Monadstypealias T = Double let f: T -> T = { $0 * 2.0 } let g: (T, T) -> T = { $0 / $1 }
f(g(4, 2))
g: (T, T) -> T?
g(4, 2) >>- { f($0) }
Monads
>>-==
http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html
Monadsfunc flatten<U>(a: U??) -> U? { switch a { case .Some(let someA): return someA case .None: return .None } }
Monadsfunc flatMap<U>(f: T -> U?) -> U? { return flatten(map(f)) }
func map<U>(f: T -> U) -> U?
func map<U?>(f: T -> U?) -> U??
Monads
infix operator >>- { associativity left }
func >>-<T, U>(a: T?, f: T -> U?) -> U? { return a.flatMap(f) }
Monadsfunc half(a: Int) -> Int? { return a % 2 == 0 ? a / 2 : .None }
Optional(8) >>- half >>- half // Optional(2)
Left Identity Lawlet f = { Optional($0 + 1) } let a = 1
let x = Optional(a) >>- f let y = f(a)
x == y
Right Identity Lawfunc create<T>(value: T) -> T? { return Optional(value) }
let x = Optional(1) >>- create let y = Optional(1)
x == y
Associativity Law
let double = { Optional(2 * $0) } let triple = { Optional(3 * $0) }
let x = Optional(1) >>- double >>- triple let y = Optional(1) >>- { double($0) >>- triple } let z = { Optional(1) >>- double }() >>- triple
x == y y == z
RecapFunctor map<U>(f: T -> U) -> M<U>
Applicative apply<U>(f: M<(T -> U)>) -> M<U>
Monad flatMap<U>(f: T -> M<U>) -> M<U>
Pipesinfix operator |> { associativity left }
public func |> <T, U>(x: T, f: T -> U) -> U { return f(x) }
let addTwo = { $0 + 2 } let prodThree = { $0 * 3 }
5 |> addTwo |> prodThree |> print // 21
Pipeslet transformedX = x |> addTwo |> prodThree |> increment |> square |> pow
VS (pow(square(increment(prodThree(addTwo(x))))))
Railways
http://fsharpforfunandprofit.com/posts/recipe-part2/
Argo Exampleextension Model: Decodable { static func decode(json: JSON) -> Decoded<Model> {
return Model.create <^> json <| "id" <*> json <| "room" <*> json <| "guest_name" <*> json <| "status" <*> json <| "label" <*> json <|? "user_comment" <*> json <| ["channel", "label"] <*> json <| "severity" <*> json <|| "epochs" <*> json <|| "body" } }
Where Next• Functors, Applicatives and Monads in Pictures
• Railway Oriented Programming
• Functional Programming in Swift (Objc.io)
• Argo
• Swiftz
• RxSwift
• ReactiveCocoa-3.0
• Haskell, F#, Erlang, Elm