View
575
Download
6
Category
Preview:
Citation preview
Теории и практики функционального программирования
Акуляков АртёмСИБИНФОСОФТ
11-я конференция .NET разработчиков31 октября 2015dotnetconf.ru
ООП против ФП
SOLID
IoC
GRASP
GangOfFour
MVC, MVP, MVVM
CQRS
EventSourcing
DDD
...
Functions
Type
Composition
7
Функции это тоже значения
let getCalc f x y = fun z -> (f x) + y + z
let calc = getCalc toX10 1 2
let result = calc value
10
Композиция : функции
let read (x : string) : int = int(x)
let mult (x : int) : int = x * x
let write (x : int) : string = string(x)
12
Композиция : функции
let readMultWrite1 x = write (mult (read x))
// x : string -> string
let readMultWrite2 = read >> mult >> write
// string -> string
13
Композиция : функции#операторыкомпозиции
let (>>) f1 f2 = fun p -> f1 f2 plet (<<) f1 f2 = fun p -> f2 f1 p
16
Композиция : функции #каррирование
let add x y = x + y // int -> int -> int
let add2 = add 2 // int -> int
let res = add2 2 // val res : int = 4
19
Композиция : типы
type LevelName = stringtype UID = int
type HierarchyIdentifier = | Plain of UID | Complex of LevelName*HierarchyIdentifier
23
DI
public class BasketCostTranslator : IBasketCostTranslator{ private readonly IExchangeRateProvider _provider;
public BasketCostTranslator(IExchangeRateProvider p) { // =) }
public BasketCost TranslateCost(BasketCost cost, Currency currency) { // =) }}
26
DI#кариррованиекакdi
type ICostTranslator = BasketCost -> BasketCost
let costTranslator exchangeProvider currency basket = // =)
let translator = costTranslator cbeRateProviderlet toUsdTranslator = translator Currency.USD
27
DI#кариррованиекакdi
type ICostTranslator = BasketCost -> BasketCost
let costTranslator exchangeProvider currency basket = // =)
let translator = costTranslator cbeRateProviderlet toUsdTranslator = translator Currency.USD
28
DI#кариррованиекакdi
type ICostTranslator = BasketCost -> BasketCost
let costTranslator exchangeProvider currency basket = // =)
let translator = costTranslator cbeRateProviderlet toUsdTranslator = translator Currency.USD
29
DI#кариррованиекакdi
type ICostTranslator = BasketCost -> BasketCost
let costTranslator exchangeProvider currency basket = // =)
let translator = costTranslator cbeRateProviderlet toUsdTranslator = translator Currency.USD
30
Мемоизация#чистыефункции
let add100 x = x + 100
add100 10 // val it : int = 110add100 10 // val it : int = 110add100 20 // val it : int = 120
34
Мемоизация#ультракеширование
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
35
Мемоизация#ультракеширование
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
36
Что не так с обычным кэшированием?
● Кэш устарел, а данные не изменились– Лишняя нагрузка
● Данные изменились, а кэш еще нет– Пользователи видят неактуальные данные
37
Сухой итог
● Функциональное программирование это просто● Можно использовать привычные приемы, но
проще● Можно заимствовать из функционального
программирования хитрые приемы
43
Полезности
http://www.intuit.ru/studies/courses/471/327/info
https://github.com/fsprojects/FSharpx.Extras
https://github.com/jack-pappas/ExtCore/
http://fsharpforfunandprofit.com/
44
Что не так с обычной обработкой ошибок?
Исключения прекрасны, но велик соблазн «логики на исключениях»
47
Обработка ошибок #идеальныймир
let handleRequest = readRequest >> readEntityFromDB >> modifyEntity >> createTaskFromEntity >> writeTaskToMQ >> createResultMessage >> sendMessage
48
Обработка ошибок 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
51
'a → Result<'b>
» 'b → Result<'c>
» 'c → Result<'d>
» …
Типы не совпадают...
53
Обработка ошибок#неработает
Обработка ошибок 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
56
Обработка ошибок#паттернобнаружен
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
57
Обработка ошибок#связываем
let bind f = fun x -> match x with | Success r -> f r | Error -> x
('a → Result<'b>) → (Result<'a> → Result<'b>)
58
Обработка ошибок#композиция
let handleRequest = readRequest >> (bind readEntityFromDB) >> (bind modifyEntity) >> (bind createTaskFromEntity) >> (bind writeTaskToMQ) >> (bind createResultMessage)
59
Обработка ошибок#композиция
let handleRequest = readRequest >>= readEntityFromDB >>= modifyEntity >>= createTaskFromEntity >>= writeTaskToMQ >>= createResultMessage
60
Сухой итог
● Функциональное программирование это просто● Можно использовать привычные приемы, но
проще● Можно заимствовать из функционального
программирования хитрые приемы● Монады совсем нестрашные
62
Recommended