Quem sou eu
• Mestre em Computação pelo IME-USP
• Desenvolvedor C desde 2002
• Objective-C desde 2007 (coisas básicas em Mac OS X antes do iPhone!)
• iOS desde 2010
• Swift desde Agosto/2015
• Tech Lead na Concrete Solutions (estamos contratando)
• Organizador do CocoaHeads SP
• Colaborador do CocoaHeads BR
• Colaborador da Embaixada Brasileira de Appsterdam
Compartilhando código e dependências entre plataformas
Escrevendo uma vez e reutilizando em iOS,
tvOS, watchOS, macOS 😂
Ou…
…veja bem…
Como alterei o tema da minha palestra
E esqueci de enviar a atualização
Usando POP com Programação Funcional
Como entender algumas abstrações usando
Protocol Oriented Programming
A Formula
• Descreva em linguagem natural
• Escreva a assinatura do tipo
• Implemente a logica
• Teste seu código
(não necessariamente nessa ordem)
O que é programação funcional?
• Estilo de programação
• First Class Functions
• Modularização
• Efeitos colaterais
• Imutabilidade
O que é programação funcional?
A monad is just a monoid in the category of endofunctors, what's the
problem?
Crockford’s Law
In addition to its being good and useful, it's also cursed. The curse of
the monad is that once you get the epiphany, once you understand oh,
that's what it is, you lose the ability to explain it to anybody else.
Três protocolos/conceitos
protocol Concattable {
init()
func +(left: Self, right: Self) -> Self
static func concat(list: [Self]) -> Self
}
extension Concattable {
static func concat(list: [Self]) -> Self {
return list.reduce(Self(), combine: +)
}
}
extension Int: Concattable {}
extension Float: Concattable {}
extension String: Concattable {}
extension Array: Concattable {}
func +<T>(left: Set<T>, right: Set<T>) -> Set<T> {
return left.union(right)
}
func +(left: Bool, right: Bool) -> Bool {
return left || right
}
func +<Key, Value>(inout left: Dictionary<Key, Value>,
right:Dictionary<Key, Value>) -> Dictionary<Key, Value> {
for (key, value) in right {
left.updateValue(value, forKey: key)
}
}
protocol Concattable {
init()
func +(left: Self, right: Self) -> Self
static func concat(list: [Self]) -> Self
}
protocol Concattable {
init()
static func concat(left: Self,
right: Self) -> Self
static func concat(list: [Self]) -> Self
}
protocol Concattable {
func makeEmpty() -> Self
func concat(left: Self,
right: Self) -> Self
func concat(list: [Self]) -> Self
}
protocol Concattable {
static func empty() -> Self
static func append(left: Self,
right: Self) -> Self
static func concat(list: [Self]) -> Self
}
protocol Concattable {
static func empty() -> Self
static func append(Self, Self) -> Self
static func concat([Self]) -> Self
}
protocol Concattable {
static func empty() -> m
static func append(m, m) -> m
static func concat([m]) -> m
}
protocol Mappable {
associatedtype Element
func map<OutType>(transform: Element -> OutType) -> Self<OutType>
}
protocol Mappable {
associatedtype Element
static func map<OutType,
OutMappable: Mappable where Element == OutType>(
transform: (Element -> OutType)
) -> OutMappable
}
extension Array: Mappable {
func map<OutType>(transform: (Element -> OutType)) -> [OutType] {
var result = Array<OutType>()
for e in self {
result.append(transform(e))
}
return result
}
}
enum Result<ValueType>: Mappable {
case Failure(error: ErrorType)
case Success(value: ValueType)
func map<OutType>(transform: ValueType -> OutType) ->
Result<OutType> {
switch self {
case .Failure(let error): return .Failure(error)
case .Success(let value):
return .Success(value: transform(value))
}
}
}
protocol Mappable {
associatedtype Element
func map<OutType,
OutMappable: Mappable where Element == OutType>(
transform: (Element -> OutType)
) -> OutMappable
}
protocol Mappable {
associatedtype Element
func map<A, B>(transform: A -> B,
input: Self<A>) -> Self<B>
}
protocol Mappable {
func map(transform: a -> b,
input: Self a) -> Self b
}
protocol Mappable {
func map(a -> b, Self a) -> Self b
}
protocol FlatMappable: Mappable {
init(element: Element)
func flatMap<Out>(transform: Element -> Self<Out>) -> Self<Out>
}
protocol FlatMappable: Mappable {
init(element: Element)
func flatMap<OutType,
OutMappable: FlatMappable where Element == OutType>(
transform: Element -> OutType) -> OutMappable
}
extension Optional: FlatMappable {
typealias Element = Wrapped
func flatMap<Out>(transform: Wrapped -> Optional<Out>) -> Optional<Out> {
switch self {
case .None: return nil
case .Some(let value): return transform(value)
}
}
}
Futures e Promises
Future - objeto mantendo um valor que pode estar disponível em algum
momento
• se o bloco de execução não terminou, dizemos que o Future ainda não
terminou
• ao completar a execução, temos um valor ou um erro - Result FTW
Promise - “extensão” do Future
• Pode retornar um Future
• Promise pode não completar/executar
• read/write
Futures
Future precisa de:
• Contexto de execução
• Tarefa a ser executada
class Future<T> {
typealias Runnable = () -> Result<T>
typealias OnSuccessCallBack = (T) -> ()
typealias OnFailueCallBack = (NSError) -> ()
typealias OnComplete = (result: Result<T>) -
//wrapper de dispatch_queue_t > ()
let extension: ExecutionContext
var result: Result<T>? = nil {
didSet {
self.performCallbacks()
}
}
}
extension Future {
func then<U>(executor: ExecutionContext =
ExecutionContext.defaultContext, task: (value: T) -> Result<U>) ->
Future<U> {
let future = Future<U>()
self.onComplete() { result in
switch result {
case .Error(let e):
syncronized(future) {
future.result = Result<U>(e)
}
case .Value(let v):
future.execute(executor) {
return task(value: result.value!)
}
}
}
}
}
class Promise<T>: Future<T> {
func success(v: T) {
}
func failure(e: NSError) {
}
}
future {
if let cached = self.cachedData() {
cached.success(cachedData)
}
return retriveData(url).flatMap( deserialize($0))
}.onSuccess { items in
self.updateUI(items)
self.cacheItems(items)
}
cached.onSuccess { items in
self.updateUI(items)
}
protocol FlatMappable: Mappable {
init(element: Element)
func flatMap<Out>(transform: Element -> Self<Out>) -> Self<Out>
}
protocol Bindable: Mappable {
init(element: Element)
func bind<Out>(
input: Self<In>,
transform: In -> Self<Out>) -> Self<Out>
}
protocol FlatMappable: Mappable {
func empty() -> m
func flatMap(a -> m b) -> m b
}
Para fins educacionais
protocol ~> class
protocol Concattable {
func empty() -> m
func append(m, m) -> m
func concat([m]) -> m
}
class Monoid m where
mempty :: m
mappend :: m -> m -> m
mconcat :: [m] -> m
Ja falamos de
Monoid
protocol Mappable {
func map(a -> b, Self a) -> Self b
}
class Functor f where
fmap :: (a -> b) -> f a -> f b
Ja falamos de
Monoid
Functor
protocol FlatMappable: Mappable {
func empty() -> m
func flatMap(a -> m b) -> m b
}
class Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
Ja falamos de
Monoid
Functor
Monad
De modo simples..
protocol ~> class
Concattable ~> Monoid
Mappable ~> Functor
FlatMappable ~> Monad
A monad is just a monoid in the category of endofunctors, what's the
problem?
http://stackoverflow.com/questions/3870088/a-monad-is-just-a-monoid-in-the-
category-of-endofunctors-whats-the-issue
Incompleto: piada criada em “A Brief, Incomplete, and Mostly Wrong History
of Programming Languages”
Qual o problema?
Então, o que é uma Monad?
All told, a monad in X is just a monoid in the category of endofunctors of X,
with product × replaced by composition of endofunctors and unit set by the
identity endofunctor.
A monad is just a monoid in the category of endofunctors, what's the
problem?
Vs
Então, o que é uma Monad?
Uma forma de criar complexidade, partindo de simplicidade
Monads famosas em Haskell (ainda não implementadas em Swift)
• I/O Monad
• State Monad
• Reader/Writer Monad
• Continuation Monad
Outras coisas que podem ser criadas
com monads
• Frameworks reativos
• DSL
• trabalho com coleções (LINQ)
Outras referências
• Finally Understand Monads with this One Weird Trick by Andy Bartholomew
• Monads are Not Monsters by Junior Bontognali
• Don’t Fear the Monads by Bryan Beckman
• Abstraction, intuition, and the “monad tutorial fallacy” by Brent
• Haskell for Mac - App Store
Outras referências
@talesp
tales.andrade@concretesolutions.com.br
Obrigado :)
www.concretesolutions.com.br
blog.concretesolutions.com.br
Rio de Janeiro – Rua São José, 90 – cj. 2121
Centro – (21) 2240-2030
São Paulo - Rua Sansão Alves dos Santos, 433
4º andar - Brooklin - (11) 4119-0449

Usando POP com Programação Funcional

  • 2.
    Quem sou eu •Mestre em Computação pelo IME-USP • Desenvolvedor C desde 2002 • Objective-C desde 2007 (coisas básicas em Mac OS X antes do iPhone!) • iOS desde 2010 • Swift desde Agosto/2015 • Tech Lead na Concrete Solutions (estamos contratando) • Organizador do CocoaHeads SP • Colaborador do CocoaHeads BR • Colaborador da Embaixada Brasileira de Appsterdam
  • 3.
    Compartilhando código edependências entre plataformas Escrevendo uma vez e reutilizando em iOS, tvOS, watchOS, macOS 😂
  • 4.
  • 5.
    Como alterei otema da minha palestra E esqueci de enviar a atualização
  • 6.
    Usando POP comProgramação Funcional Como entender algumas abstrações usando Protocol Oriented Programming
  • 7.
    A Formula • Descrevaem linguagem natural • Escreva a assinatura do tipo • Implemente a logica • Teste seu código (não necessariamente nessa ordem)
  • 8.
    O que éprogramação funcional? • Estilo de programação • First Class Functions • Modularização • Efeitos colaterais • Imutabilidade
  • 9.
    O que éprogramação funcional? A monad is just a monoid in the category of endofunctors, what's the problem? Crockford’s Law In addition to its being good and useful, it's also cursed. The curse of the monad is that once you get the epiphany, once you understand oh, that's what it is, you lose the ability to explain it to anybody else.
  • 10.
  • 11.
    protocol Concattable { init() func+(left: Self, right: Self) -> Self static func concat(list: [Self]) -> Self }
  • 12.
    extension Concattable { staticfunc concat(list: [Self]) -> Self { return list.reduce(Self(), combine: +) } }
  • 13.
    extension Int: Concattable{} extension Float: Concattable {} extension String: Concattable {} extension Array: Concattable {}
  • 14.
    func +<T>(left: Set<T>,right: Set<T>) -> Set<T> { return left.union(right) } func +(left: Bool, right: Bool) -> Bool { return left || right }
  • 15.
    func +<Key, Value>(inoutleft: Dictionary<Key, Value>, right:Dictionary<Key, Value>) -> Dictionary<Key, Value> { for (key, value) in right { left.updateValue(value, forKey: key) } }
  • 16.
    protocol Concattable { init() func+(left: Self, right: Self) -> Self static func concat(list: [Self]) -> Self }
  • 17.
    protocol Concattable { init() staticfunc concat(left: Self, right: Self) -> Self static func concat(list: [Self]) -> Self }
  • 18.
    protocol Concattable { funcmakeEmpty() -> Self func concat(left: Self, right: Self) -> Self func concat(list: [Self]) -> Self }
  • 19.
    protocol Concattable { staticfunc empty() -> Self static func append(left: Self, right: Self) -> Self static func concat(list: [Self]) -> Self }
  • 20.
    protocol Concattable { staticfunc empty() -> Self static func append(Self, Self) -> Self static func concat([Self]) -> Self }
  • 21.
    protocol Concattable { staticfunc empty() -> m static func append(m, m) -> m static func concat([m]) -> m }
  • 22.
    protocol Mappable { associatedtypeElement func map<OutType>(transform: Element -> OutType) -> Self<OutType> }
  • 23.
    protocol Mappable { associatedtypeElement static func map<OutType, OutMappable: Mappable where Element == OutType>( transform: (Element -> OutType) ) -> OutMappable }
  • 24.
    extension Array: Mappable{ func map<OutType>(transform: (Element -> OutType)) -> [OutType] { var result = Array<OutType>() for e in self { result.append(transform(e)) } return result } }
  • 25.
    enum Result<ValueType>: Mappable{ case Failure(error: ErrorType) case Success(value: ValueType) func map<OutType>(transform: ValueType -> OutType) -> Result<OutType> { switch self { case .Failure(let error): return .Failure(error) case .Success(let value): return .Success(value: transform(value)) } } }
  • 26.
    protocol Mappable { associatedtypeElement func map<OutType, OutMappable: Mappable where Element == OutType>( transform: (Element -> OutType) ) -> OutMappable }
  • 27.
    protocol Mappable { associatedtypeElement func map<A, B>(transform: A -> B, input: Self<A>) -> Self<B> }
  • 28.
    protocol Mappable { funcmap(transform: a -> b, input: Self a) -> Self b }
  • 29.
    protocol Mappable { funcmap(a -> b, Self a) -> Self b }
  • 30.
    protocol FlatMappable: Mappable{ init(element: Element) func flatMap<Out>(transform: Element -> Self<Out>) -> Self<Out> }
  • 31.
    protocol FlatMappable: Mappable{ init(element: Element) func flatMap<OutType, OutMappable: FlatMappable where Element == OutType>( transform: Element -> OutType) -> OutMappable }
  • 32.
    extension Optional: FlatMappable{ typealias Element = Wrapped func flatMap<Out>(transform: Wrapped -> Optional<Out>) -> Optional<Out> { switch self { case .None: return nil case .Some(let value): return transform(value) } } }
  • 33.
    Futures e Promises Future- objeto mantendo um valor que pode estar disponível em algum momento • se o bloco de execução não terminou, dizemos que o Future ainda não terminou • ao completar a execução, temos um valor ou um erro - Result FTW Promise - “extensão” do Future • Pode retornar um Future • Promise pode não completar/executar • read/write
  • 34.
    Futures Future precisa de: •Contexto de execução • Tarefa a ser executada
  • 35.
    class Future<T> { typealiasRunnable = () -> Result<T> typealias OnSuccessCallBack = (T) -> () typealias OnFailueCallBack = (NSError) -> () typealias OnComplete = (result: Result<T>) - //wrapper de dispatch_queue_t > () let extension: ExecutionContext var result: Result<T>? = nil { didSet { self.performCallbacks() } } }
  • 36.
    extension Future { functhen<U>(executor: ExecutionContext = ExecutionContext.defaultContext, task: (value: T) -> Result<U>) -> Future<U> { let future = Future<U>() self.onComplete() { result in switch result { case .Error(let e): syncronized(future) { future.result = Result<U>(e) } case .Value(let v): future.execute(executor) { return task(value: result.value!) } } } } }
  • 37.
    class Promise<T>: Future<T>{ func success(v: T) { } func failure(e: NSError) { } }
  • 38.
    future { if letcached = self.cachedData() { cached.success(cachedData) } return retriveData(url).flatMap( deserialize($0)) }.onSuccess { items in self.updateUI(items) self.cacheItems(items) } cached.onSuccess { items in self.updateUI(items) }
  • 39.
    protocol FlatMappable: Mappable{ init(element: Element) func flatMap<Out>(transform: Element -> Self<Out>) -> Self<Out> }
  • 40.
    protocol Bindable: Mappable{ init(element: Element) func bind<Out>( input: Self<In>, transform: In -> Self<Out>) -> Self<Out> }
  • 41.
    protocol FlatMappable: Mappable{ func empty() -> m func flatMap(a -> m b) -> m b }
  • 42.
  • 43.
    protocol Concattable { funcempty() -> m func append(m, m) -> m func concat([m]) -> m }
  • 44.
    class Monoid mwhere mempty :: m mappend :: m -> m -> m mconcat :: [m] -> m
  • 45.
  • 46.
    protocol Mappable { funcmap(a -> b, Self a) -> Self b }
  • 47.
    class Functor fwhere fmap :: (a -> b) -> f a -> f b
  • 48.
  • 49.
    protocol FlatMappable: Mappable{ func empty() -> m func flatMap(a -> m b) -> m b }
  • 50.
    class Monad mwhere return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b
  • 51.
  • 52.
    De modo simples.. protocol~> class Concattable ~> Monoid Mappable ~> Functor FlatMappable ~> Monad
  • 53.
    A monad isjust a monoid in the category of endofunctors, what's the problem? http://stackoverflow.com/questions/3870088/a-monad-is-just-a-monoid-in-the- category-of-endofunctors-whats-the-issue Incompleto: piada criada em “A Brief, Incomplete, and Mostly Wrong History of Programming Languages” Qual o problema?
  • 54.
    Então, o queé uma Monad? All told, a monad in X is just a monoid in the category of endofunctors of X, with product × replaced by composition of endofunctors and unit set by the identity endofunctor. A monad is just a monoid in the category of endofunctors, what's the problem? Vs
  • 55.
    Então, o queé uma Monad? Uma forma de criar complexidade, partindo de simplicidade Monads famosas em Haskell (ainda não implementadas em Swift) • I/O Monad • State Monad • Reader/Writer Monad • Continuation Monad
  • 56.
    Outras coisas quepodem ser criadas com monads • Frameworks reativos • DSL • trabalho com coleções (LINQ)
  • 57.
    Outras referências • FinallyUnderstand Monads with this One Weird Trick by Andy Bartholomew • Monads are Not Monsters by Junior Bontognali • Don’t Fear the Monads by Bryan Beckman • Abstraction, intuition, and the “monad tutorial fallacy” by Brent • Haskell for Mac - App Store
  • 58.
  • 59.
    www.concretesolutions.com.br blog.concretesolutions.com.br Rio de Janeiro– Rua São José, 90 – cj. 2121 Centro – (21) 2240-2030 São Paulo - Rua Sansão Alves dos Santos, 433 4º andar - Brooklin - (11) 4119-0449

Notas do Editor

  • #12 API guidelines: evite termos obscuros e nomeie habilidades com sufixo “able” operadores dentro de protocolos são estáticos
  • #14 aplicar a inteiros e floats soma os valores. Em strings o conteúdo é concatenado. Em arrays os novos valores são adicionados no fim do array
  • #17 API guidelines: evite termos obscuros e nomeie habilidades com sufixo “able” operadores dentro de protocolos são estáticos
  • #18 init constroi uma nova instancia vazia,
  • #19 pra evitar ambiguidade, renomeados o primeiro concat
  • #20 append não é muito bom, indica mutabilidade
  • #25 esse código derruba o compilador :(
  • #33 não compila :(
  • #36 encadeamento
  • #40 para fins educacionais…
  • #41 flatmappable -> bindable flatmap -> bind
  • #42 flatmappable -> bindable flatmap -> bind
  • #55 endofunctor é um functor com algumas regras adicionais X é uma categoria
  • #56 I/O - controla efeito colateral no IO (disco, rede, etc) - puramente funcional State - maquina de estados com efeitos intermediários Writer ~ Log - resultado+valor associado Reader ~ Continuation ~ controla “efeito colateral” em callbacks
  • #57 I/O - controla efeito colateral no IO (disco, rede, etc) - puramente funcional State - maquina de estados com efeitos intermediários Writer ~ Log - resultado+valor associado Reader ~ Continuation ~ controla “efeito colateral” em callbacks
  • #58 I/O - controla efeito colateral no IO (disco, rede, etc) - puramente funcional State - maquina de estados com efeitos intermediários Writer ~ Log - resultado+valor associado Reader ~ Continuation ~ controla “efeito colateral” em callbacks
  • #59 I/O - controla efeito colateral no IO (disco, rede, etc) - puramente funcional State - maquina de estados com efeitos intermediários Writer ~ Log - resultado+valor associado Reader ~ Continuation ~ controla “efeito colateral” em callbacks