Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Functional Programming in Swift

Functional Programming in Swift

Talk about Functional Programming in Swift from NSConfArg 2015

Avatar for Adrián Ferreyra

Adrián Ferreyra

April 11, 2015

Other Decks in Programming

Transcript

  1. Bases de Functional Programming. ✓ Composición de funciones. Monoides. Monads.

    Funciones de orden superior. Functors. Usted está aquí.
  2. Operador Composición //Definición de operator infijo infix operator >>> {

    associativity left precedence 100 } //Definición de la función func >>> <A>(f: A->A, g: A->A) -> A -> A { return { x in g(f(x)) } }
  3. func blur10(image:CIImage) -> CIImage { let filter = CIFilter(name: "CIGaussianBlur",

    withInputParameters: [kCIInputRadiusKey: 10, kCIInputImageKey: image]); return filter.outputImage; }
  4. func sepia(image:CIImage) -> CIImage { let filter = CIFilter(name: “CISepiaTone",

    withInputParameters: [kCIInputIntensityKey: 0.8, kCIInputImageKey: image]); return filter.outputImage; }
  5. infix operator >>> {associativity left} func >>>(f1:Filter, f2:Filter) -> Filter

    { return {(x:CIImage) in f2(f1(x))} } let composedFilter = sepia >>> blur10
  6. Monoid Dado un espacio de funciones con el mismo tipo

    •Operación binaria asociativa cerrada Operador composición >>> func f <A>(param: A) -> A { … } func g <A>(param: A) -> A { … } •Elemento Identidad func id <A>(param: A) -> A { return param }
  7. Bases de Functional Programming. ✓ Composición de funciones. ✓ Monoides.

    ✓ Monads. Funciones de orden superior. Functors. Usted está aquí.
  8. let payments = [40,20,50,30,15,25,60] var filteredArray : [Int] = []

    for money in payments { if (money > 30) { filteredArray += [money] } }
  9. let acumulator = payments.reduce(0, combine: { $0 + $1 }

    ) let payments = [40,20,50,30,15,25,60]
  10. Toma los elementos de un array, les aplica una transformación

    y devuelve un array con los resultados. Map
  11. let payments = [40,20,50,30,15,25,60] var modifiedPayments: [Double] = [] for

    money in payments { modifiedPayments.append(Double(money) * 1.1) }
  12. Map Toma un contenedor, les aplica una transformación y devuelve

    el contenedor con los resultados. Es posible definir Map para cualquier contenedor de datos
  13. let array = [40,20,50,30,15,25,60] let tuple = ("Hello there!”,123) let

    optionalString = Optional("Hello there!") let dictionary = {"value":123} enum Result<A> { case Exists(A) case None }
  14. Bases de Functional Programming. ✓ Composición de funciones. ✓ Monoides.

    ✓ Monads. Funciones de orden superior. ✓ Functors. ✓ Usted está aquí.
  15. Monad • Bind Operation func flatMap <U>(f: A -> M<U>)

    -> M<U> { return self.flatten(self.map(f)) } FlatMap (Bind)
  16. func f <A>(a:A)->A {… return a} // A -> A

    func g <A>(a:A)->A {… return a} // A -> A >>> // (A -> A, A -> A) -> (A -> A) ✅
  17. func f <A>(a:A)->M<A> { return M(a) } // A ->

    M<A> func g <A>(a:A)->M<A> { return M(a) } // A -> M<A> >>> // (A -> A, A -> A) -> (A -> A) ❌
  18. func f <A>(a: A) -> M<A> { return M(a) }

    // A -> M<A> func g <A>(a: A) -> M<A> { return M(a) } // A -> M<A> var composition = {(a:Int) in f(a) >>= g} // \ A -> { (M<A>, transformación: A -> M<A>) -> M<A> } // \ A -> M<A> ✅
  19. class Future<A> { var result: FutureResult<A> init () { result

    = .NotFinished } init (_ x:A) { result = .Finished(x) } }
  20. func bind <B>(f:A? -> Future<B>) -> Future<B> { var returnFuture

    = Future<B>() self.callback = {(x:A?) in var secondFuture = f(x) secondFuture.callback = { (y:B?) -> Void in returnFuture.result = .Finished(y) } } return returnFuture }
  21. func getURL (s:String?) -> Future<NSURL> { var returnFuture = Future<NSURL>()

    if let unwrappedString = s { returnFuture.result = .Finished(NSURL(string: unwrappedString)) } else { returnFuture.result = .Finished(nil) } return returnFuture }
  22. func httpGet (s:NSURL?) -> Future<NSData> { println("httpGet") var returnFuture =

    Future<NSData>() if let unwrappedURL = s { let task = NSURLSession.sharedSession().dataTaskWithURL(unwrappedURL) {(data, response, error) in if((error) != nil) { returnFuture.result = .Finished(nil) } else { returnFuture.result = .Finished(data) } } task.resume() } else { returnFuture.result = .Finished(nil) } return returnFuture }
  23. func responseString (data:NSData?) -> Future<String> { println("responseString") var returnFuture =

    Future<String>() if let unwrappedData = data { returnFuture.result = .Finished(NSString(data: unwrappedData, encoding: NSUTF8StringEncoding) as? String) } else { returnFuture.result = .Finished(nil) } return returnFuture }
  24. let getResponseString = { unit($0) >>>= getURL >>>= httpGet >>>=

    responseString } let response = getResponseString("http://nsconfarg.com") response.callback = {println("\($0)")}
  25. Funcionalmente modular. Diseñamos pensando en funcionalidades, no de los componentes

    del sistema. Composition is the only way to control complexity.