![Page 1: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/1.jpg)
Теории и практики функционального
программирования
Акуляков Артем
![Page 2: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/2.jpg)
Кто я?
● 5+ лет dotNet interpraise● 2+ лет python freelance● 2+ I love FP
● Докладчик dotnetconf, dev2dev● Организатор it-сообщества dev2dev
2
![Page 3: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/3.jpg)
К чему это все?
3
![Page 4: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/4.jpg)
К чему это все?
● ФП устарело.
4
![Page 5: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/5.jpg)
ФП устарело, но вот эти ребята еще не в курсе...
5
![Page 6: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/6.jpg)
К чему это все?
● ФП устарело.● ФП применимо только в узком круге задач.
6
![Page 7: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/7.jpg)
Веб-приложение
HttpRequest → HttpResponse
7
![Page 8: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/8.jpg)
Веб-приложение
function (HttpRequest) → HttpResponse
8
![Page 9: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/9.jpg)
К чему это все?
● ФП устарело.● ФП применимо только в узком круге задач.
● Я БОЮСЬ ФУНКЦИОНАЛЬНОГО ПРОГРАММИРОВАНИЯ!
9
![Page 10: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/10.jpg)
Поговорим об ООП
10
![Page 11: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/11.jpg)
ООП против ФП● SOLID● IoC● GRASP● GangOfFour● MVC, MVP, MVVM● CQRS● EventSourcing● DDD● ...
11
![Page 12: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/12.jpg)
ООП против ФП● SOLID● IoC● GRASP● GangOfFour● MVC, MVP, MVVM● CQRS● EventSourcing● DDD● ...
● Functions● Type● Composition
12
![Page 13: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/13.jpg)
ООП против ФП● SOLID● IoC● GRASP● GangOfFour● MVC, MVP, MVVM● CQRS● EventSourcing● DDD● ...
● Functions● Type● Composition
● Monads, Monoids...
13
![Page 14: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/14.jpg)
Основы функционального программирования
14
![Page 15: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/15.jpg)
Функции это тоже значения
15
![Page 16: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/16.jpg)
Функции это тоже значения
let value = 5
let toX10 = fun x -> x * 10
16
![Page 17: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/17.jpg)
Функции это тоже значения
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](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/18.jpg)
Композиция
18
![Page 19: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/19.jpg)
Композиция : функции
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](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/20.jpg)
Композиция : функции
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](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/21.jpg)
Композиция
a → b » b → ca → c
21
![Page 22: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/22.jpg)
Композиция
a → b » b → c » ... » x → za → z
22
![Page 23: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/23.jpg)
Композиция : функции#операторыкомпозиции
let (>>) f1 f2 p = f2(f1 p)let (<<) f1 f2 p = f1(f2 p)
23
![Page 24: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/24.jpg)
Композиция : функции#конвейерныеоператоры
let (|>) p f = func paramlet (<|) f p = func param
24
![Page 25: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/25.jpg)
Проблема...Операторы композиции и
конвейера определены только для функций с одним аргументом
25
![Page 26: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/26.jpg)
Решение!Все функции это на самом деле функции от одного аргумента
26
![Page 27: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/27.jpg)
Композиция : функции #каррирование
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](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/28.jpg)
Типы
28
![Page 29: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/29.jpg)
Типы#обзор
type Alias = inttype FunctionAlias = int -> int
29
![Page 30: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/30.jpg)
Типы#обзор
type Record = { field1 : int; field2 : string }
30
![Page 31: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/31.jpg)
Типы#обзор
type DiscriminatedUnion = | Variant1 of int | Variant2 of string
type Enum = | One = 1 | Two = 2 | Three = 3
31
![Page 32: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/32.jpg)
Типы это не классы
32
![Page 33: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/33.jpg)
Композиция : типы
type NodeName = stringtype UID = int
type HierarchyIdentifier = | Plain of UID | Complex of NodeName*HierarchyIdentifier
33
![Page 34: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/34.jpg)
Композиция: типы
Complex(NodeName * Complex
(NodeName * Complex(Plain)
))
34
![Page 35: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/35.jpg)
ООП и ФП имеют много общих концепций
35
![Page 36: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/36.jpg)
Interfaces & SRP
public interface IExchangeRateProvider { ExchangeRate GetRate(Currency currency); }
public class ExchangeProvider : IExchangeRateProvider { public ExchangeRate GetRate(Currency currency) { // =) } }
36
![Page 37: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/37.jpg)
Interfaces & SRP#типыфункцийкакинтерфейсы
type IExchangeRateProvider = Currency -> ExchangeRate
let exchangeRateProvider(currency:Currency):ExchangeRate = // =)
37
![Page 38: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/38.jpg)
DI
public class BasketCostTranslator : IBasketCostTranslator{ private readonly IExchangeRateProvider _provider;
public BasketCostTranslator(IExchangeRateProvider p) { // =) }
public BasketCost TranslateCost(BasketCost cost) { // =) }}
38
![Page 39: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/39.jpg)
DI#кариррованиекакdi
type ICostTranslator = BasketCost -> BasketCost
let costTranslator exchangeProvider basket = // =)
let translator = costTranslator exchangeRateProvider
39
![Page 40: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/40.jpg)
Шаблонный метод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](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/41.jpg)
Шаблонный метод
public class ComplexDeliveryCalculator: SimpleDeliveryCalculator{ protected override int CalculatePackagesCount(
IEnumerable<PurchaseDimensions> purchases) { // "complex" calculation }}
41
![Page 42: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/42.jpg)
Шаблонный метод#композициярулит
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](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/43.jpg)
Декоратор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](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/44.jpg)
Декоратор#исновакомпозициярулит
let loggingDecorator provider currency = // log something let result = provider currency // log something result
let provider = loggingDecorator exchangeRateProvider
44
![Page 45: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/45.jpg)
Декоратор#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](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/46.jpg)
Кое-что интересное из мира ФП
46
![Page 47: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/47.jpg)
Мемоизация
47
![Page 48: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/48.jpg)
Мемоизация#чистыефункции
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](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/49.jpg)
Мемоизация#ультракеширование
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](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/50.jpg)
Мемоизация#ультракеширование
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](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/51.jpg)
Мемоизация#ультракеширование
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](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/52.jpg)
Мемоизация#практика
function (HttpRequest) → HttpResponse
52
![Page 53: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/53.jpg)
Мемоизация#практика
function (HttpRequest, DbState) → HttpResponse
53
![Page 54: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/54.jpg)
Мемоизация#практика
https://github.com/Suor/django-cacheops
54
![Page 55: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/55.jpg)
Обработка ошибок
55
![Page 56: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/56.jpg)
Обработка ошибок #идеальныймир
let handleRequest = readRequest >> readEntityFromDB >> modifyEntity >> createTaskFromEntity >> writeTaskToMQ >> createResultMessage >> sendMessage
56
![Page 57: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/57.jpg)
Мир неидеален
57
![Page 58: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/58.jpg)
Обработка ошибок
type Result<'r> = | Success of 'r | Error
// 'r -> Result<'r>
58
![Page 59: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/59.jpg)
Обработка ошибок 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](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/60.jpg)
А как же композиция?
»
60
![Page 61: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/61.jpg)
Обработка ошибок#неработает
'a → Result<'b>
» 'b → Result<'c>
» 'c → Result<'d>
» …
Типы не совпадают...
61
![Page 62: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/62.jpg)
Обработка ошибок#решение
Нужно преобразование
('a → Result<'c>) → (Result<'a> → Result<'c>)
62
![Page 63: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/63.jpg)
Обработка ошибок#решение
Нужно преобразование
('a → Result<'c>) → (Result<'a> → Result<'c>)
Как?
63
![Page 64: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/64.jpg)
Обработка ошибок 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](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/65.jpg)
Обработка ошибок#паттернобнаружен
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](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/66.jpg)
Обработка ошибок#связываем
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](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/67.jpg)
Обработка ошибок#композиция
let handleRequest = readRequest >> (bind readEntityFromDB) >> (bind modifyEntity) >> (bind createTaskFromEntity) >> (bind writeTaskToMQ) >> (bind createResultMessage)
67
![Page 68: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/68.jpg)
Мы только что изобрели монаду
68
![Page 69: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/69.jpg)
Сухой итог
● Функциональное программирование это просто● Можно использовать привычные приемы, но
проще● Можно заимствовать из функционального
программирования хитрые приемы● Монады совсем не страшные
69
![Page 70: Теории и практики фунционального программирования - GDG D2D](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/70.jpg)
Полезности
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](https://reader030.vdocuments.pub/reader030/viewer/2022033022/58840a341a28ab95518b462b/html5/thumbnails/71.jpg)
Вопросы?
71