Теории и практики фунционального программирования - gdg...

71
Теории и практики функционального программирования Акуляков Артем

Upload: 0xffaa

Post on 22-Jan-2017

219 views

Category:

Engineering


0 download

TRANSCRIPT

Page 1: Теории и практики фунционального программирования - GDG D2D

Теории и практики функционального

программирования

Акуляков Артем

Page 2: Теории и практики фунционального программирования - GDG D2D

Кто я?

● 5+ лет dotNet interpraise● 2+ лет python freelance● 2+ I love FP

● Докладчик dotnetconf, dev2dev● Организатор it-сообщества dev2dev

2

Page 3: Теории и практики фунционального программирования - GDG D2D

К чему это все?

3

Page 4: Теории и практики фунционального программирования - GDG D2D

К чему это все?

● ФП устарело.

4

Page 5: Теории и практики фунционального программирования - GDG D2D

ФП устарело, но вот эти ребята еще не в курсе...

5

Page 6: Теории и практики фунционального программирования - GDG D2D

К чему это все?

● ФП устарело.● ФП применимо только в узком круге задач.

6

Page 7: Теории и практики фунционального программирования - GDG D2D

Веб-приложение

HttpRequest → HttpResponse

7

Page 8: Теории и практики фунционального программирования - GDG D2D

Веб-приложение

function (HttpRequest) → HttpResponse

8

Page 9: Теории и практики фунционального программирования - GDG D2D

К чему это все?

● ФП устарело.● ФП применимо только в узком круге задач.

● Я БОЮСЬ ФУНКЦИОНАЛЬНОГО ПРОГРАММИРОВАНИЯ!

9

Page 10: Теории и практики фунционального программирования - GDG D2D

Поговорим об ООП

10

Page 11: Теории и практики фунционального программирования - GDG D2D

ООП против ФП● SOLID● IoC● GRASP● GangOfFour● MVC, MVP, MVVM● CQRS● EventSourcing● DDD● ...

11

Page 12: Теории и практики фунционального программирования - GDG D2D

ООП против ФП● SOLID● IoC● GRASP● GangOfFour● MVC, MVP, MVVM● CQRS● EventSourcing● DDD● ...

● Functions● Type● Composition

12

Page 13: Теории и практики фунционального программирования - GDG D2D

ООП против ФП● SOLID● IoC● GRASP● GangOfFour● MVC, MVP, MVVM● CQRS● EventSourcing● DDD● ...

● Functions● Type● Composition

● Monads, Monoids...

13

Page 14: Теории и практики фунционального программирования - GDG D2D

Основы функционального программирования

14

Page 15: Теории и практики фунционального программирования - GDG D2D

Функции это тоже значения

15

Page 16: Теории и практики фунционального программирования - GDG D2D

Функции это тоже значения

let value = 5

let toX10 = fun x -> x * 10

16

Page 17: Теории и практики фунционального программирования - GDG D2D

Функции это тоже значения

let getCalc f x y = fun z -> (f x) + y + z

let calc = getCalc toX10 1 2

let result = calc value

17

Page 18: Теории и практики фунционального программирования - GDG D2D

Композиция

18

Page 19: Теории и практики фунционального программирования - GDG D2D

Композиция : функции

let read (x : string) : int = int(x)

let mult (x : int) : int = x * x

let write (x : int) : string = string(x)

19

Page 20: Теории и практики фунционального программирования - GDG D2D

Композиция : функции

let readMultWrite1 x = write (mult (read x))

// x : string -> string

let readMultWrite2 = read >> mult >> write

// string -> string

let readMultWrite3 x = x |> read |> mult |> write

// x : string -> string

20

Page 21: Теории и практики фунционального программирования - GDG D2D

Композиция

a → b » b → ca → c

21

Page 22: Теории и практики фунционального программирования - GDG D2D

Композиция

a → b » b → c » ... » x → za → z

22

Page 23: Теории и практики фунционального программирования - GDG D2D

Композиция : функции#операторыкомпозиции

let (>>) f1 f2 p = f2(f1 p)let (<<) f1 f2 p = f1(f2 p)

23

Page 24: Теории и практики фунционального программирования - GDG D2D

Композиция : функции#конвейерныеоператоры

let (|>) p f = func paramlet (<|) f p = func param

24

Page 25: Теории и практики фунционального программирования - GDG D2D

Проблема...Операторы композиции и

конвейера определены только для функций с одним аргументом

25

Page 26: Теории и практики фунционального программирования - GDG D2D

Решение!Все функции это на самом деле функции от одного аргумента

26

Page 27: Теории и практики фунционального программирования - GDG D2D

Композиция : функции #каррирование

let add x y = x + y // int -> int -> int

let add2 = add 2 // int -> int

let res = add2 2 // val res : int = 4

27

Page 28: Теории и практики фунционального программирования - GDG D2D

Типы

28

Page 29: Теории и практики фунционального программирования - GDG D2D

Типы#обзор

type Alias = inttype FunctionAlias = int -> int

29

Page 30: Теории и практики фунционального программирования - GDG D2D

Типы#обзор

type Record = { field1 : int; field2 : string }

30

Page 31: Теории и практики фунционального программирования - GDG D2D

Типы#обзор

type DiscriminatedUnion = | Variant1 of int | Variant2 of string

type Enum = | One = 1 | Two = 2 | Three = 3

31

Page 32: Теории и практики фунционального программирования - GDG D2D

Типы это не классы

32

Page 33: Теории и практики фунционального программирования - GDG D2D

Композиция : типы

type NodeName = stringtype UID = int

type HierarchyIdentifier = | Plain of UID | Complex of NodeName*HierarchyIdentifier

33

Page 34: Теории и практики фунционального программирования - GDG D2D

Композиция: типы

Complex(NodeName * Complex

(NodeName * Complex(Plain)

))

34

Page 35: Теории и практики фунционального программирования - GDG D2D

ООП и ФП имеют много общих концепций

35

Page 36: Теории и практики фунционального программирования - GDG D2D

Interfaces & SRP

public interface IExchangeRateProvider { ExchangeRate GetRate(Currency currency); }

public class ExchangeProvider : IExchangeRateProvider { public ExchangeRate GetRate(Currency currency) { // =) } }

36

Page 37: Теории и практики фунционального программирования - GDG D2D

Interfaces & SRP#типыфункцийкакинтерфейсы

type IExchangeRateProvider = Currency -> ExchangeRate

let exchangeRateProvider(currency:Currency):ExchangeRate = // =)

37

Page 38: Теории и практики фунционального программирования - GDG D2D

DI

public class BasketCostTranslator : IBasketCostTranslator{ private readonly IExchangeRateProvider _provider;

public BasketCostTranslator(IExchangeRateProvider p) { // =) }

public BasketCost TranslateCost(BasketCost cost) { // =) }}

38

Page 39: Теории и практики фунционального программирования - GDG D2D

DI#кариррованиекакdi

type ICostTranslator = BasketCost -> BasketCost

let costTranslator exchangeProvider basket = // =)

let translator = costTranslator exchangeRateProvider

39

Page 40: Теории и практики фунционального программирования - GDG D2D

Шаблонный методpublic class SimpleDeliveryCalculator : IDeliveryCostCalculator{ public DeliveryOffer Calculate(

IEnumerable<PurchaseDimensions> purchases) { // do something var packagesCount = CalculatePackagesCount(purchases); // do something }

protected virtual int CalculatePackagesCount(IEnumerable<PurchaseDimensions> purchases)

{ // calculation }}

40

Page 41: Теории и практики фунционального программирования - GDG D2D

Шаблонный метод

public class ComplexDeliveryCalculator: SimpleDeliveryCalculator{ protected override int CalculatePackagesCount(

IEnumerable<PurchaseDimensions> purchases) { // "complex" calculation }}

41

Page 42: Теории и практики фунционального программирования - GDG D2D

Шаблонный метод#композициярулит

let deliveryCalculator packagesCalculator purchases = // do something let packagesCount = packagesCalculator purchases // do something

let simpleCalculatePackages purchases = // do something

let complexCalculatePackages purchases = //do something

let calculator1 = deliveryCalculator simpleCalculatePackageslet calculator2 = deliveryCalculator complexCalculatePackages

42

Page 43: Теории и практики фунционального программирования - GDG D2D

Декораторpublic class LoggingDecorator : IExchangeRateProvider{ private IExchangeRateProvider _service;

public LoggingDecorator(IExchangeRateProvider service) { ... }

public ExchangeRate GetRate(Currency currency) { // log something var result = _service.GetRate(currency); // log something return result; }}

43

Page 44: Теории и практики фунционального программирования - GDG D2D

Декоратор#исновакомпозициярулит

let loggingDecorator provider currency = // log something let result = provider currency // log something result

let provider = loggingDecorator exchangeRateProvider

44

Page 45: Теории и практики фунционального программирования - GDG D2D

Декоратор#pyдекораторыпрекрасны

def logging(func): def wrapper(*args, **kwargs): res = func(*args, **kwargs) print(func.__name__, args, kwargs) return res return wrapper

@loggingdef adder(x, y): return x + y

adder(1, 2)

45

Page 46: Теории и практики фунционального программирования - GDG D2D

Кое-что интересное из мира ФП

46

Page 47: Теории и практики фунционального программирования - GDG D2D

Мемоизация

47

Page 48: Теории и практики фунционального программирования - GDG D2D

Мемоизация#чистыефункции

let adder x = x + 100

adder 10 // val it : int = 110adder 10 // val it : int = 110adder 20 // val it : int = 120

48

Page 49: Теории и практики фунционального программирования - GDG D2D

Мемоизация#ультракеширование

let memoize (f: 'a -> 'b) = let dict = new Dictionary<'a, 'b>() let memoized (input: 'a) = match dict.TryGetValue(input) with | true, x -> x | false, _ -> let result = f input dict.Add(input, result) result memoized

let memAdder = memoize adder

49

Page 50: Теории и практики фунционального программирования - GDG D2D

Мемоизация#ультракеширование

let memoize (f: 'a -> 'b) = let dict = new Dictionary<'a, 'b>() let memoized (input: 'a) = match dict.TryGetValue(input) with | true, x -> x | false, _ -> let result = f input dict.Add(input, result) result memoized

let memAdder = memoize adder

50

Page 51: Теории и практики фунционального программирования - GDG D2D

Мемоизация#ультракеширование

let memoize (f: 'a -> 'b) = let dict = new Dictionary<'a, 'b>() let memoized (input: 'a) = match dict.TryGetValue(input) with | true, x -> x | false, _ -> let result = f input dict.Add(input, result) result memoized

let memAdder = memoize adder

51

Page 52: Теории и практики фунционального программирования - GDG D2D

Мемоизация#практика

function (HttpRequest) → HttpResponse

52

Page 53: Теории и практики фунционального программирования - GDG D2D

Мемоизация#практика

function (HttpRequest, DbState) → HttpResponse

53

Page 54: Теории и практики фунционального программирования - GDG D2D

Мемоизация#практика

https://github.com/Suor/django-cacheops

54

Page 55: Теории и практики фунционального программирования - GDG D2D

Обработка ошибок

55

Page 56: Теории и практики фунционального программирования - GDG D2D

Обработка ошибок #идеальныймир

let handleRequest = readRequest >> readEntityFromDB >> modifyEntity >> createTaskFromEntity >> writeTaskToMQ >> createResultMessage >> sendMessage

56

Page 57: Теории и практики фунционального программирования - GDG D2D

Мир неидеален

57

Page 58: Теории и практики фунционального программирования - GDG D2D

Обработка ошибок

type Result<'r> = | Success of 'r | Error

// 'r -> Result<'r>

58

Page 59: Теории и практики фунционального программирования - GDG D2D

Обработка ошибок let handleRequest s = match readRequest s with | Success r -> match readEntityFromDB r with | Success e -> match modifyEntity e with | Success me -> match createTaskFromEntity me with | Success t -> match writeTaskToMQ t with | Success ts -> createResultMessage ts | Error -> Error | Error -> Error | Error -> Error | Error -> Error | Error -> Error

59

Page 60: Теории и практики фунционального программирования - GDG D2D

А как же композиция?

»

60

Page 61: Теории и практики фунционального программирования - GDG D2D

Обработка ошибок#неработает

'a → Result<'b>

» 'b → Result<'c>

» 'c → Result<'d>

» …

Типы не совпадают...

61

Page 62: Теории и практики фунционального программирования - GDG D2D

Обработка ошибок#решение

Нужно преобразование

('a → Result<'c>) → (Result<'a> → Result<'c>)

62

Page 63: Теории и практики фунционального программирования - GDG D2D

Обработка ошибок#решение

Нужно преобразование

('a → Result<'c>) → (Result<'a> → Result<'c>)

Как?

63

Page 64: Теории и практики фунционального программирования - GDG D2D

Обработка ошибок let handleRequest s = match readRequest s with | Success r -> match readEntityFromDB r with | Success e -> match modifyEntity e with | Success me -> match createTaskFromEntity me with | Success t -> match writeTaskToMQ t with | Success ts -> createResultMessage ts | Error -> Error | Error -> Error | Error -> Error | Error -> Error | Error -> Error

64

Page 65: Теории и практики фунционального программирования - GDG D2D

Обработка ошибок#паттернобнаружен

let handleRequest s = match readRequest s with | Success r -> match readEntityFromDB r with | Success e -> match modifyEntity e with | Success me -> match createTaskFromEntity me with | Success t -> match writeTaskToMQ t with | Success ts -> createResultMessage ts | Error -> Error | Error -> Error | Error -> Error | Error -> Error | Error -> Error

65

Page 66: Теории и практики фунционального программирования - GDG D2D

Обработка ошибок#связываем

let bind f = fun x -> match x with | Success r -> f r | Error -> x

('a → Result<'b>) → (Result<'a> → Result<'b>)

66

Page 67: Теории и практики фунционального программирования - GDG D2D

Обработка ошибок#композиция

let handleRequest = readRequest >> (bind readEntityFromDB) >> (bind modifyEntity) >> (bind createTaskFromEntity) >> (bind writeTaskToMQ) >> (bind createResultMessage)

67

Page 68: Теории и практики фунционального программирования - GDG D2D

Мы только что изобрели монаду

68

Page 69: Теории и практики фунционального программирования - GDG D2D

Сухой итог

● Функциональное программирование это просто● Можно использовать привычные приемы, но

проще● Можно заимствовать из функционального

программирования хитрые приемы● Монады совсем не страшные

69

Page 70: Теории и практики фунционального программирования - GDG D2D

Полезности

http://www.intuit.ru/studies/courses/471/327/info

https://github.com/fsprojects/FSharpx.Extras

https://github.com/jack-pappas/ExtCore/

http://fsharpforfunandprofit.com/

70

Page 71: Теории и практики фунционального программирования - GDG D2D

Вопросы?

71