SlideShare ist ein Scribd-Unternehmen logo
1 von 56
Downloaden Sie, um offline zu lesen
TDD with F# (since 2003)
Anton Moldovan (@antyadev)
SBTech
Twitter: https://twitter.com/antyaDev
Github: https://github.com/antyaDev
About me:
@AntyaDev
like types*
@ploeh
@ploeh
@ploeh
@ploeh
Free
monads






In OOP you by default thinking about
abstraction
extensibility
In FP you by default thinking about
purity
composability
correctness
In FP you build your ideal, private world
where
you know
everything
Pure
Domain
If you are coming from an object-oriented design background, one of
the paradigm shifts involved in "thinking functionally" is to change how
you think about types.
A well designed object-oriented program will have:
• a strong focus on behavior rather than data,
• will use a lot of polymorphism (interfaces),
• will try to avoid having explicit knowledge of the actual concrete
classes being passed around.
A well designed functional program, on the other hand, will have a
strong focus on data types rather than behavior
type UserName = {
firstName: string
lastName: string
}
type Shape =
| Circle of int
| Rectangle of int * int
type UserName = {
firstName: string;
lastName: string
}
let a = { firstName = "a"; lastName = "b" }
let b = { firstName = "a"; lastName = "b" }
if a = b then "equals" // true
type Money = {
amount: decimal
currency: Currency
}
let a = { amount = 10; currency = USD }
let b = { amount = 10; currency = USD }
if a = b then "equals" // true
type Shape =
| Rectangle = 0
| Circle = 1
| Prism = 2
type Shape =
| Rectangle of width:float * length:float
| Circle of radius:float
| Prism of width:float * float * height:float
let rectangle = Rectangle(width = 6.2, length = 5.5)
anyone can set this to ‘true’
Rule 1: if the email is changed, the verified flag must be reset to ‘false’.
Rule 2: the verified flag can only be set by a special verification service.
Rule 3: we have 5 services which works only for verified email
and 5 services which works for invalid email.
class EmailContact
{
public string EmailAddress { get; set; }
public bool IsEmailVerified { get; set; }
}
Rule 3: we have - 5 services which works only for verified email
and - 5 services which works for invalid email.
if (emailContract.IsEmailVerified)
void SendEmailToApprove(EmailContact emailContract)
{
if (emailContract.IsEmailVerified)
}
void SendEmailToReject(EmailContact emailContract)
{
if (emailContract.IsEmailVerified)
}
void SendEmailToConfirm(EmailContact emailContract)
{
if (emailContract.IsEmailVerified)
}
void SendEmailToLinkedin(EmailContact emailContract)
{
if (emailContract.IsEmailVerified)
}
type ValidEmail = { email: string }
type InvalidEmail = { email: string }
type Email =
| Valid of ValidEmail
| Invalid of InvalidEmail
let sendEmailToLinkedin (email: ValidEmail) = ...
You need only one dispatch in one place
•
•
•
public class NaiveShoppingCart<TItem>
{
private List<TItem> items;
private decimal paidAmount;
public NaiveShoppingCart()
{
this.items = new List<TItem>();
this.paidAmount = 0;
}
/// Is cart paid for?
public bool IsPaidFor => this.paidAmount > 0;
public IEnumerable<TItem> Items => this.items;
public void AddItem(TItem item)
{
if (!this.IsPaidFor) this.items.Add(item);
}
if (!this.IsPaidFor) { do something }
public class NaiveShoppingCart<TItem>
{
private List<TItem> items;
public bool IsPaidFor => this.paidAmount > 0;
public bool IsPaidFor => this.paidAmount > 0;
public bool IsConfirmedByUser => _isConfirmedByUser;
public bool IsApproved => IsPaidFor && _isValid;
public bool IsCanceledByUser => _isCanceled && _user != null;
public bool IsCanceledAuto => _isCanceled || _user == null && _system != null;
public bool IsCanceledAdmin => _isCanceled || _user == null && _system == null && _admin != null;
public Status GetStatus()
{
if (_isCanceled && items.Count > 0)
return Status.Invalid;
else if (items.Count > 0)
return Status.Active;
return Status.Empty;
}
public void Approve()
{
if (_isCanceled) throw new Exception();
if (items.Count > 0)
}
what about recently added IsCanceledByAdmin?
•
•
•
type CartItem = string // placeholder for a more complicated type
type EmptyState = NoItems
type ActiveState = { unpaidItems: CartItem list; }
type PaidForState = { paidItems: CartItem list; payment: decimal}
type Cart =
| Empty of EmptyState
| Active of ActiveState
| PaidFor of PaidForState
type EmptyState = NoItems
type ActiveState = { unpaidItems: CartItem list; }
type PaidForState = { paidItems: CartItem list; payment: decimal }
type Cart =
| Empty of EmptyState
| Active of ActiveState
| PaidFor of PaidForState
// =============================
// operations on empty state
// =============================
let addToEmptyState (item: CartItem) : Cart.Active =
Cart.Active { unpaidItems = [item] } // a new Active Cart
type EmptyState = NoItems
type ActiveState = { unpaidItems: CartItem list; }
type PaidForState = { paidItems: CartItem list; payment: decimal }
type Cart =
| Empty of EmptyState
| Active of ActiveState
| PaidFor of PaidForState
// =============================
// operation on empty state
// =============================
let addToEmptyState item =
{ unpaidItems = [item] } // returns a new Active Cart
type EmptyState = NoItems
type ActiveState = { unpaidItems: CartItem list; }
type PaidForState = { paidItems: CartItem list; payment: decimal }
type Cart =
| Empty of EmptyState
| Active of ActiveState
| PaidFor of PaidForState
// =============================
// operation on active state
// =============================
let addToActiveState (state: ActiveState, itemToAdd: CartItem) =
let newList = itemToAdd :: state.unpaidItems
Cart.Active { state with unpaidItems = newList }
type EmptyState = NoItems
type ActiveState = { unpaidItems: CartItem list; }
type PaidForState = { paidItems: CartItem list; payment: decimal }
type Cart =
| Empty of EmptyState
| Active of ActiveState
| PaidFor of PaidForState
// =============================
// operation on active state
// =============================
let addToActiveState state itemToAdd =
let newList = itemToAdd :: state.unpaidItems
{ state with unpaidItems = newList }
type EmptyState = NoItems
type ActiveState = { unpaidItems: CartItem list; }
type PaidForState = { paidItems: CartItem list; payment: decimal }
type Cart =
| Empty of EmptyState
| Active of ActiveState
| PaidFor of PaidForState
let removeFromActiveState state itemToRemove =
let newList = state.unpaidItems
|> List.filter (fun i -> i <> itemToRemove)
match newList with
| [] -> Cart.Empty NoItems
| _ -> Cart.Active { state with unpaidItems = newList }
type EmptyState = NoItems
type ActiveState = { unpaidItems: CartItem list; }
type PaidForState = { paidItems: CartItem list; payment: decimal }
type Cart =
| Empty of EmptyState
| Active of ActiveState
| PaidFor of PaidForState
let payForActiveState state amount =
Cart.PaidFor { paidItems = state.unpaidItems
payment = amount }
type EmptyState = NoItems
type ActiveState = { unpaidItems: CartItem list; }
type PaidForState = { paidItems: CartItem list; payment: decimal}
type Cart =
| Empty of EmptyState
| Active of ActiveState
| PaidFor of PaidForState
let item = “test_product”
let activeState = addToEmptyState(item)
let paidState = payForActiveState(activeState, 10)
// compile error, your state is not active anymore
let activeState = addToActiveState(paidState, item)
errors
let failingFunc num =
let x = raise (new System.Exception("fail!"))
try
let y = 42 + 5 + num
x + y
with
e -> 43
/// Represents the result of a computation
type Result<'ok, 'msg> =
| Ok of 'ok * 'msg list
| Fail of 'msg list
type Request = { name: string; email: string }
let validateInput input =
if input.name = ""
then Fail("Name must not be blank")
elif input.email = ""
then Fail("Email must not be blank")
else Ok(input)
type Request = { name: string; email: string }
let validateInput input =
if input.name = ""
then fail "Name must not be blank"
elif input.email = ""
then fail "Email must not be blank"
else ok input
let validate1 input =
if input.name = "" then fail "Name must not be blank“
else ok input
let validate2 input =
if input.name.Length > 50 then fail "Name must not be longer than 50 chars"
else ok input
let validate3 input =
if input.email = "" then fail "Email must not be blank"
else ok input
let validRequest = validate1 >>= validate2 >>= validate3 >>= validate4
In functional programming we strive to write side-effect free
applications. In other words, all the functions of the
application should be pure. However, completely side-effect
free applications are mostly useless, so the next best thing is
to minimize the amount of side-effects, make them
explicit and push them as close to the boundaries of the
application as possible.
Let’s see an example in invoicing domain. When changing a due date of
an invoice we want to check that the new due date is in the future. We
could implement it like this:
let changeDueDate (newDueDate:DateTime, invoice) =
if newDueDate > System.DateTime.Today
then ok { invoice with dueDate = newDueDate }
else fail "Due date must be in future."
let changeDueDate (newDueDate:DateTime,
currentDate:DateTime, invoice) =
if newDueDate > currentDate
then ok { invoice with dueDate = newDueDate }
else fail "Due date must be in future."
type PastDate = PastDate of DateTime
type CurrentDate = CurrentDate of DateTime
type FutureDate = FutureDate of DateTime
type Date =
| Past of PastDate
| Current of CurrentDate
| Future of FutureDate
let changeDueDate (newDueDate:FutureDate, invoice) =
{ invoice with DueDate = Date newDueDate }
Problem: Language do not integrate information
- We need to bring information into the language…
Антон Молдован "Type driven development with f#"
Антон Молдован "Type driven development with f#"
Антон Молдован "Type driven development with f#"

Weitere ähnliche Inhalte

Was ist angesagt?

Visual basic asp.net programming introduction
Visual basic asp.net programming introductionVisual basic asp.net programming introduction
Visual basic asp.net programming introductionHock Leng PUAH
 
Javascript variables and datatypes
Javascript variables and datatypesJavascript variables and datatypes
Javascript variables and datatypesVarun C M
 
Railway Oriented Programming
Railway Oriented ProgrammingRailway Oriented Programming
Railway Oriented ProgrammingScott Wlaschin
 
Clean Code: Chapter 3 Function
Clean Code: Chapter 3 FunctionClean Code: Chapter 3 Function
Clean Code: Chapter 3 FunctionKent Huang
 
Communicating Intention with Functional TypeScript
Communicating Intention with Functional TypeScriptCommunicating Intention with Functional TypeScript
Communicating Intention with Functional TypeScriptThiago Temple
 
Linq 090701233237 Phpapp01
Linq 090701233237 Phpapp01Linq 090701233237 Phpapp01
Linq 090701233237 Phpapp01google
 
Presentatioon on type conversion and escape characters
Presentatioon on type conversion and escape charactersPresentatioon on type conversion and escape characters
Presentatioon on type conversion and escape charactersfaala
 
Notes for GNU Octave - Numerical Programming - for Students - 02 of 02 by aru...
Notes for GNU Octave - Numerical Programming - for Students - 02 of 02 by aru...Notes for GNU Octave - Numerical Programming - for Students - 02 of 02 by aru...
Notes for GNU Octave - Numerical Programming - for Students - 02 of 02 by aru...ssuserd6b1fd
 
The Ring programming language version 1.5.2 book - Part 6 of 181
The Ring programming language version 1.5.2 book - Part 6 of 181The Ring programming language version 1.5.2 book - Part 6 of 181
The Ring programming language version 1.5.2 book - Part 6 of 181Mahmoud Samir Fayed
 
MVC Design Pattern in JavaScript by ADMEC Multimedia Institute
MVC Design Pattern in JavaScript by ADMEC Multimedia InstituteMVC Design Pattern in JavaScript by ADMEC Multimedia Institute
MVC Design Pattern in JavaScript by ADMEC Multimedia InstituteRavi Bhadauria
 
Iterative control structures, looping, types of loops, loop working
Iterative control structures, looping, types of loops, loop workingIterative control structures, looping, types of loops, loop working
Iterative control structures, looping, types of loops, loop workingNeeru Mittal
 

Was ist angesagt? (20)

Javascript essentials
Javascript essentialsJavascript essentials
Javascript essentials
 
Visual basic asp.net programming introduction
Visual basic asp.net programming introductionVisual basic asp.net programming introduction
Visual basic asp.net programming introduction
 
Javascript variables and datatypes
Javascript variables and datatypesJavascript variables and datatypes
Javascript variables and datatypes
 
PHP - Introduction to PHP Forms
PHP - Introduction to PHP FormsPHP - Introduction to PHP Forms
PHP - Introduction to PHP Forms
 
Javascript
JavascriptJavascript
Javascript
 
Railway Oriented Programming
Railway Oriented ProgrammingRailway Oriented Programming
Railway Oriented Programming
 
Java scriptfunction
Java scriptfunctionJava scriptfunction
Java scriptfunction
 
Clean Code: Chapter 3 Function
Clean Code: Chapter 3 FunctionClean Code: Chapter 3 Function
Clean Code: Chapter 3 Function
 
Anonymous functions in JavaScript
Anonymous functions in JavaScriptAnonymous functions in JavaScript
Anonymous functions in JavaScript
 
Communicating Intention with Functional TypeScript
Communicating Intention with Functional TypeScriptCommunicating Intention with Functional TypeScript
Communicating Intention with Functional TypeScript
 
Linq 090701233237 Phpapp01
Linq 090701233237 Phpapp01Linq 090701233237 Phpapp01
Linq 090701233237 Phpapp01
 
Presentatioon on type conversion and escape characters
Presentatioon on type conversion and escape charactersPresentatioon on type conversion and escape characters
Presentatioon on type conversion and escape characters
 
Notes for GNU Octave - Numerical Programming - for Students - 02 of 02 by aru...
Notes for GNU Octave - Numerical Programming - for Students - 02 of 02 by aru...Notes for GNU Octave - Numerical Programming - for Students - 02 of 02 by aru...
Notes for GNU Octave - Numerical Programming - for Students - 02 of 02 by aru...
 
The Ring programming language version 1.5.2 book - Part 6 of 181
The Ring programming language version 1.5.2 book - Part 6 of 181The Ring programming language version 1.5.2 book - Part 6 of 181
The Ring programming language version 1.5.2 book - Part 6 of 181
 
Whats New In C# 3.0
Whats New In C# 3.0Whats New In C# 3.0
Whats New In C# 3.0
 
Javascript
JavascriptJavascript
Javascript
 
Marcus Portfolio
Marcus  PortfolioMarcus  Portfolio
Marcus Portfolio
 
MVC Design Pattern in JavaScript by ADMEC Multimedia Institute
MVC Design Pattern in JavaScript by ADMEC Multimedia InstituteMVC Design Pattern in JavaScript by ADMEC Multimedia Institute
MVC Design Pattern in JavaScript by ADMEC Multimedia Institute
 
Javascript ch7
Javascript ch7Javascript ch7
Javascript ch7
 
Iterative control structures, looping, types of loops, loop working
Iterative control structures, looping, types of loops, loop workingIterative control structures, looping, types of loops, loop working
Iterative control structures, looping, types of loops, loop working
 

Andere mochten auch

Сергей Калинец "Стероиды для Дотнетчика"
Сергей Калинец "Стероиды для Дотнетчика"Сергей Калинец "Стероиды для Дотнетчика"
Сергей Калинец "Стероиды для Дотнетчика"Fwdays
 
Сергей Радзыняк ".NET Microservices in Real Life"
Сергей Радзыняк ".NET Microservices in Real Life"Сергей Радзыняк ".NET Microservices in Real Life"
Сергей Радзыняк ".NET Microservices in Real Life"Fwdays
 
Владимир Никонов "Вызовы при разработке enterprise продукта"
Владимир Никонов "Вызовы при разработке enterprise продукта"Владимир Никонов "Вызовы при разработке enterprise продукта"
Владимир Никонов "Вызовы при разработке enterprise продукта"Fwdays
 
Евгений Напрягло ".NET Framework Hosting API Overview"
Евгений Напрягло ".NET Framework Hosting API Overview"Евгений Напрягло ".NET Framework Hosting API Overview"
Евгений Напрягло ".NET Framework Hosting API Overview"Fwdays
 
Сергей Поплавский "DeepDive в Bot платформу Microsoft. Технические аспекты ра...
Сергей Поплавский "DeepDive в Bot платформу Microsoft. Технические аспекты ра...Сергей Поплавский "DeepDive в Bot платформу Microsoft. Технические аспекты ра...
Сергей Поплавский "DeepDive в Bot платформу Microsoft. Технические аспекты ра...Fwdays
 
Игорь Леонтьев "Azure Container Service: not only Docker"
Игорь Леонтьев "Azure Container Service: not only Docker"Игорь Леонтьев "Azure Container Service: not only Docker"
Игорь Леонтьев "Azure Container Service: not only Docker"Fwdays
 
Евгений Остапчук "Tips&Tricks for ASP.NET MVC performance"
Евгений Остапчук "Tips&Tricks for ASP.NET MVC performance"Евгений Остапчук "Tips&Tricks for ASP.NET MVC performance"
Евгений Остапчук "Tips&Tricks for ASP.NET MVC performance"Fwdays
 
Денис Резник "Зачем мне знать SQL и Базы Данных, ведь у меня есть ORM?"
Денис Резник "Зачем мне знать SQL и Базы Данных, ведь у меня есть ORM?"Денис Резник "Зачем мне знать SQL и Базы Данных, ведь у меня есть ORM?"
Денис Резник "Зачем мне знать SQL и Базы Данных, ведь у меня есть ORM?"Fwdays
 
Стас Султанов "Assembling Solutions with Microsoft Azure"
Стас Султанов "Assembling Solutions with Microsoft Azure"Стас Султанов "Assembling Solutions with Microsoft Azure"
Стас Султанов "Assembling Solutions with Microsoft Azure"Fwdays
 
Андрей Чебукин "Построение успешных API"
Андрей Чебукин "Построение успешных API"Андрей Чебукин "Построение успешных API"
Андрей Чебукин "Построение успешных API"Fwdays
 
Игорь Фесенко "What’s New in C# 7.0"
Игорь Фесенко "What’s New in C# 7.0"Игорь Фесенко "What’s New in C# 7.0"
Игорь Фесенко "What’s New in C# 7.0"Fwdays
 
Борис Могила "Isomorphic React apps in production"
Борис Могила "Isomorphic React apps in production"Борис Могила "Isomorphic React apps in production"
Борис Могила "Isomorphic React apps in production"Fwdays
 
Алексей Волков "Еще несколько слов об архитектуре"
Алексей Волков "Еще несколько слов об архитектуре"Алексей Волков "Еще несколько слов об архитектуре"
Алексей Волков "Еще несколько слов об архитектуре"Fwdays
 
Алексей Косинский "React Native vs. React+WebView"
Алексей Косинский "React Native vs. React+WebView"Алексей Косинский "React Native vs. React+WebView"
Алексей Косинский "React Native vs. React+WebView"Fwdays
 
New Business Owner Website Questions, What Makes a Lead Generation Website Go...
New Business Owner Website Questions, What Makes a Lead Generation Website Go...New Business Owner Website Questions, What Makes a Lead Generation Website Go...
New Business Owner Website Questions, What Makes a Lead Generation Website Go...Humberto Valle MBA
 
Юлия Пучнина "PhaserJS for advertisement: игры внутри баннеров"
Юлия Пучнина "PhaserJS for advertisement: игры внутри баннеров"Юлия Пучнина "PhaserJS for advertisement: игры внутри баннеров"
Юлия Пучнина "PhaserJS for advertisement: игры внутри баннеров"Fwdays
 
Robert Browning and Elizabeth Barret ppt
Robert Browning and Elizabeth Barret pptRobert Browning and Elizabeth Barret ppt
Robert Browning and Elizabeth Barret pptValentinaPardoDiaz
 
El curriculum en los tiempos de las redes
El curriculum en los tiempos de las redesEl curriculum en los tiempos de las redes
El curriculum en los tiempos de las redesLina Pimienta
 
Gender Bias in Advertising
Gender Bias in AdvertisingGender Bias in Advertising
Gender Bias in AdvertisingMichael Wolfe
 

Andere mochten auch (20)

Сергей Калинец "Стероиды для Дотнетчика"
Сергей Калинец "Стероиды для Дотнетчика"Сергей Калинец "Стероиды для Дотнетчика"
Сергей Калинец "Стероиды для Дотнетчика"
 
Сергей Радзыняк ".NET Microservices in Real Life"
Сергей Радзыняк ".NET Microservices in Real Life"Сергей Радзыняк ".NET Microservices in Real Life"
Сергей Радзыняк ".NET Microservices in Real Life"
 
Владимир Никонов "Вызовы при разработке enterprise продукта"
Владимир Никонов "Вызовы при разработке enterprise продукта"Владимир Никонов "Вызовы при разработке enterprise продукта"
Владимир Никонов "Вызовы при разработке enterprise продукта"
 
Евгений Напрягло ".NET Framework Hosting API Overview"
Евгений Напрягло ".NET Framework Hosting API Overview"Евгений Напрягло ".NET Framework Hosting API Overview"
Евгений Напрягло ".NET Framework Hosting API Overview"
 
Сергей Поплавский "DeepDive в Bot платформу Microsoft. Технические аспекты ра...
Сергей Поплавский "DeepDive в Bot платформу Microsoft. Технические аспекты ра...Сергей Поплавский "DeepDive в Bot платформу Microsoft. Технические аспекты ра...
Сергей Поплавский "DeepDive в Bot платформу Microsoft. Технические аспекты ра...
 
Игорь Леонтьев "Azure Container Service: not only Docker"
Игорь Леонтьев "Azure Container Service: not only Docker"Игорь Леонтьев "Azure Container Service: not only Docker"
Игорь Леонтьев "Azure Container Service: not only Docker"
 
Евгений Остапчук "Tips&Tricks for ASP.NET MVC performance"
Евгений Остапчук "Tips&Tricks for ASP.NET MVC performance"Евгений Остапчук "Tips&Tricks for ASP.NET MVC performance"
Евгений Остапчук "Tips&Tricks for ASP.NET MVC performance"
 
Денис Резник "Зачем мне знать SQL и Базы Данных, ведь у меня есть ORM?"
Денис Резник "Зачем мне знать SQL и Базы Данных, ведь у меня есть ORM?"Денис Резник "Зачем мне знать SQL и Базы Данных, ведь у меня есть ORM?"
Денис Резник "Зачем мне знать SQL и Базы Данных, ведь у меня есть ORM?"
 
Стас Султанов "Assembling Solutions with Microsoft Azure"
Стас Султанов "Assembling Solutions with Microsoft Azure"Стас Султанов "Assembling Solutions with Microsoft Azure"
Стас Султанов "Assembling Solutions with Microsoft Azure"
 
Андрей Чебукин "Построение успешных API"
Андрей Чебукин "Построение успешных API"Андрей Чебукин "Построение успешных API"
Андрей Чебукин "Построение успешных API"
 
Игорь Фесенко "What’s New in C# 7.0"
Игорь Фесенко "What’s New in C# 7.0"Игорь Фесенко "What’s New in C# 7.0"
Игорь Фесенко "What’s New in C# 7.0"
 
Борис Могила "Isomorphic React apps in production"
Борис Могила "Isomorphic React apps in production"Борис Могила "Isomorphic React apps in production"
Борис Могила "Isomorphic React apps in production"
 
Алексей Волков "Еще несколько слов об архитектуре"
Алексей Волков "Еще несколько слов об архитектуре"Алексей Волков "Еще несколько слов об архитектуре"
Алексей Волков "Еще несколько слов об архитектуре"
 
Алексей Косинский "React Native vs. React+WebView"
Алексей Косинский "React Native vs. React+WebView"Алексей Косинский "React Native vs. React+WebView"
Алексей Косинский "React Native vs. React+WebView"
 
New Business Owner Website Questions, What Makes a Lead Generation Website Go...
New Business Owner Website Questions, What Makes a Lead Generation Website Go...New Business Owner Website Questions, What Makes a Lead Generation Website Go...
New Business Owner Website Questions, What Makes a Lead Generation Website Go...
 
Юлия Пучнина "PhaserJS for advertisement: игры внутри баннеров"
Юлия Пучнина "PhaserJS for advertisement: игры внутри баннеров"Юлия Пучнина "PhaserJS for advertisement: игры внутри баннеров"
Юлия Пучнина "PhaserJS for advertisement: игры внутри баннеров"
 
Robert Browning and Elizabeth Barret ppt
Robert Browning and Elizabeth Barret pptRobert Browning and Elizabeth Barret ppt
Robert Browning and Elizabeth Barret ppt
 
El curriculum en los tiempos de las redes
El curriculum en los tiempos de las redesEl curriculum en los tiempos de las redes
El curriculum en los tiempos de las redes
 
Gender Bias in Advertising
Gender Bias in AdvertisingGender Bias in Advertising
Gender Bias in Advertising
 
El Camino Recto
El Camino RectoEl Camino Recto
El Camino Recto
 

Ähnlich wie Антон Молдован "Type driven development with f#"

20 html-forms
20 html-forms20 html-forms
20 html-formsKumar
 
Tony Vitabile .Net Portfolio
Tony Vitabile .Net PortfolioTony Vitabile .Net Portfolio
Tony Vitabile .Net Portfoliovitabile
 
Web forms and html lecture Number 4
Web forms and html lecture Number 4Web forms and html lecture Number 4
Web forms and html lecture Number 4Mudasir Syed
 
SummaryHW6 Account ManagementIn HW4, you kept track of multiple.pdf
SummaryHW6 Account ManagementIn HW4, you kept track of multiple.pdfSummaryHW6 Account ManagementIn HW4, you kept track of multiple.pdf
SummaryHW6 Account ManagementIn HW4, you kept track of multiple.pdfARORACOCKERY2111
 
Csharp4 operators and_casts
Csharp4 operators and_castsCsharp4 operators and_casts
Csharp4 operators and_castsAbed Bukhari
 
Improving Correctness With Type - Goto Con Berlin
Improving Correctness With Type - Goto Con BerlinImproving Correctness With Type - Goto Con Berlin
Improving Correctness With Type - Goto Con BerlinIain Hull
 
Functional Design Patterns (DevTernity 2018)
Functional Design Patterns (DevTernity 2018)Functional Design Patterns (DevTernity 2018)
Functional Design Patterns (DevTernity 2018)Scott Wlaschin
 
ES3-2020-06 Test Driven Development (TDD)
ES3-2020-06 Test Driven Development (TDD)ES3-2020-06 Test Driven Development (TDD)
ES3-2020-06 Test Driven Development (TDD)David Rodenas
 
Loop structures chpt_6
Loop structures chpt_6Loop structures chpt_6
Loop structures chpt_6cmontanez
 
Clean code and Code Smells
Clean code and Code SmellsClean code and Code Smells
Clean code and Code SmellsMario Sangiorgio
 
The Functional Programming Toolkit (NDC Oslo 2019)
The Functional Programming Toolkit (NDC Oslo 2019)The Functional Programming Toolkit (NDC Oslo 2019)
The Functional Programming Toolkit (NDC Oslo 2019)Scott Wlaschin
 
Write a program to find the number of comparisons using the binary se.docx
 Write a program to find the number of comparisons using the binary se.docx Write a program to find the number of comparisons using the binary se.docx
Write a program to find the number of comparisons using the binary se.docxajoy21
 
05 html-forms
05 html-forms05 html-forms
05 html-formsPalakshya
 
PHP Form Validation Technique
PHP Form Validation TechniquePHP Form Validation Technique
PHP Form Validation TechniqueMorshedul Arefin
 
Should be in JavaInterface Worker should extend Serializable from .pdf
Should be in JavaInterface Worker should extend Serializable from .pdfShould be in JavaInterface Worker should extend Serializable from .pdf
Should be in JavaInterface Worker should extend Serializable from .pdffashionscollect
 
The Django Book - Chapter 7 forms
The Django Book - Chapter 7 formsThe Django Book - Chapter 7 forms
The Django Book - Chapter 7 formsVincent Chien
 

Ähnlich wie Антон Молдован "Type driven development with f#" (20)

Functional DDD
Functional DDDFunctional DDD
Functional DDD
 
20 html-forms
20 html-forms20 html-forms
20 html-forms
 
Tony Vitabile .Net Portfolio
Tony Vitabile .Net PortfolioTony Vitabile .Net Portfolio
Tony Vitabile .Net Portfolio
 
Web forms and html lecture Number 4
Web forms and html lecture Number 4Web forms and html lecture Number 4
Web forms and html lecture Number 4
 
SummaryHW6 Account ManagementIn HW4, you kept track of multiple.pdf
SummaryHW6 Account ManagementIn HW4, you kept track of multiple.pdfSummaryHW6 Account ManagementIn HW4, you kept track of multiple.pdf
SummaryHW6 Account ManagementIn HW4, you kept track of multiple.pdf
 
Csharp4 operators and_casts
Csharp4 operators and_castsCsharp4 operators and_casts
Csharp4 operators and_casts
 
Improving Correctness With Type - Goto Con Berlin
Improving Correctness With Type - Goto Con BerlinImproving Correctness With Type - Goto Con Berlin
Improving Correctness With Type - Goto Con Berlin
 
Functional Design Patterns (DevTernity 2018)
Functional Design Patterns (DevTernity 2018)Functional Design Patterns (DevTernity 2018)
Functional Design Patterns (DevTernity 2018)
 
ES3-2020-06 Test Driven Development (TDD)
ES3-2020-06 Test Driven Development (TDD)ES3-2020-06 Test Driven Development (TDD)
ES3-2020-06 Test Driven Development (TDD)
 
Loop structures chpt_6
Loop structures chpt_6Loop structures chpt_6
Loop structures chpt_6
 
Clean code and Code Smells
Clean code and Code SmellsClean code and Code Smells
Clean code and Code Smells
 
Java 2
Java   2Java   2
Java 2
 
The Functional Programming Toolkit (NDC Oslo 2019)
The Functional Programming Toolkit (NDC Oslo 2019)The Functional Programming Toolkit (NDC Oslo 2019)
The Functional Programming Toolkit (NDC Oslo 2019)
 
2. HTML forms
2. HTML forms2. HTML forms
2. HTML forms
 
Write a program to find the number of comparisons using the binary se.docx
 Write a program to find the number of comparisons using the binary se.docx Write a program to find the number of comparisons using the binary se.docx
Write a program to find the number of comparisons using the binary se.docx
 
05 html-forms
05 html-forms05 html-forms
05 html-forms
 
PHP Form Validation Technique
PHP Form Validation TechniquePHP Form Validation Technique
PHP Form Validation Technique
 
Should be in JavaInterface Worker should extend Serializable from .pdf
Should be in JavaInterface Worker should extend Serializable from .pdfShould be in JavaInterface Worker should extend Serializable from .pdf
Should be in JavaInterface Worker should extend Serializable from .pdf
 
Javascript
JavascriptJavascript
Javascript
 
The Django Book - Chapter 7 forms
The Django Book - Chapter 7 formsThe Django Book - Chapter 7 forms
The Django Book - Chapter 7 forms
 

Mehr von Fwdays

"How Preply reduced ML model development time from 1 month to 1 day",Yevhen Y...
"How Preply reduced ML model development time from 1 month to 1 day",Yevhen Y..."How Preply reduced ML model development time from 1 month to 1 day",Yevhen Y...
"How Preply reduced ML model development time from 1 month to 1 day",Yevhen Y...Fwdays
 
"GenAI Apps: Our Journey from Ideas to Production Excellence",Danil Topchii
"GenAI Apps: Our Journey from Ideas to Production Excellence",Danil Topchii"GenAI Apps: Our Journey from Ideas to Production Excellence",Danil Topchii
"GenAI Apps: Our Journey from Ideas to Production Excellence",Danil TopchiiFwdays
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr LapshynFwdays
 
"What is a RAG system and how to build it",Dmytro Spodarets
"What is a RAG system and how to build it",Dmytro Spodarets"What is a RAG system and how to build it",Dmytro Spodarets
"What is a RAG system and how to build it",Dmytro SpodaretsFwdays
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
"Distributed graphs and microservices in Prom.ua", Maksym Kindritskyi
"Distributed graphs and microservices in Prom.ua",  Maksym Kindritskyi"Distributed graphs and microservices in Prom.ua",  Maksym Kindritskyi
"Distributed graphs and microservices in Prom.ua", Maksym KindritskyiFwdays
 
"Rethinking the existing data loading and processing process as an ETL exampl...
"Rethinking the existing data loading and processing process as an ETL exampl..."Rethinking the existing data loading and processing process as an ETL exampl...
"Rethinking the existing data loading and processing process as an ETL exampl...Fwdays
 
"How Ukrainian IT specialist can go on vacation abroad without crossing the T...
"How Ukrainian IT specialist can go on vacation abroad without crossing the T..."How Ukrainian IT specialist can go on vacation abroad without crossing the T...
"How Ukrainian IT specialist can go on vacation abroad without crossing the T...Fwdays
 
"The Strength of Being Vulnerable: the experience from CIA, Tesla and Uber", ...
"The Strength of Being Vulnerable: the experience from CIA, Tesla and Uber", ..."The Strength of Being Vulnerable: the experience from CIA, Tesla and Uber", ...
"The Strength of Being Vulnerable: the experience from CIA, Tesla and Uber", ...Fwdays
 
"[QUICK TALK] Radical candor: how to achieve results faster thanks to a cultu...
"[QUICK TALK] Radical candor: how to achieve results faster thanks to a cultu..."[QUICK TALK] Radical candor: how to achieve results faster thanks to a cultu...
"[QUICK TALK] Radical candor: how to achieve results faster thanks to a cultu...Fwdays
 
"[QUICK TALK] PDP Plan, the only one door to raise your salary and boost care...
"[QUICK TALK] PDP Plan, the only one door to raise your salary and boost care..."[QUICK TALK] PDP Plan, the only one door to raise your salary and boost care...
"[QUICK TALK] PDP Plan, the only one door to raise your salary and boost care...Fwdays
 
"4 horsemen of the apocalypse of working relationships (+ antidotes to them)"...
"4 horsemen of the apocalypse of working relationships (+ antidotes to them)"..."4 horsemen of the apocalypse of working relationships (+ antidotes to them)"...
"4 horsemen of the apocalypse of working relationships (+ antidotes to them)"...Fwdays
 
"Reconnecting with Purpose: Rediscovering Job Interest after Burnout", Anast...
"Reconnecting with Purpose: Rediscovering Job Interest after Burnout",  Anast..."Reconnecting with Purpose: Rediscovering Job Interest after Burnout",  Anast...
"Reconnecting with Purpose: Rediscovering Job Interest after Burnout", Anast...Fwdays
 
"Mentoring 101: How to effectively invest experience in the success of others...
"Mentoring 101: How to effectively invest experience in the success of others..."Mentoring 101: How to effectively invest experience in the success of others...
"Mentoring 101: How to effectively invest experience in the success of others...Fwdays
 
"Mission (im) possible: How to get an offer in 2024?", Oleksandra Myronova
"Mission (im) possible: How to get an offer in 2024?",  Oleksandra Myronova"Mission (im) possible: How to get an offer in 2024?",  Oleksandra Myronova
"Mission (im) possible: How to get an offer in 2024?", Oleksandra MyronovaFwdays
 
"Why have we learned how to package products, but not how to 'package ourselv...
"Why have we learned how to package products, but not how to 'package ourselv..."Why have we learned how to package products, but not how to 'package ourselv...
"Why have we learned how to package products, but not how to 'package ourselv...Fwdays
 
"How to tame the dragon, or leadership with imposter syndrome", Oleksandr Zin...
"How to tame the dragon, or leadership with imposter syndrome", Oleksandr Zin..."How to tame the dragon, or leadership with imposter syndrome", Oleksandr Zin...
"How to tame the dragon, or leadership with imposter syndrome", Oleksandr Zin...Fwdays
 

Mehr von Fwdays (20)

"How Preply reduced ML model development time from 1 month to 1 day",Yevhen Y...
"How Preply reduced ML model development time from 1 month to 1 day",Yevhen Y..."How Preply reduced ML model development time from 1 month to 1 day",Yevhen Y...
"How Preply reduced ML model development time from 1 month to 1 day",Yevhen Y...
 
"GenAI Apps: Our Journey from Ideas to Production Excellence",Danil Topchii
"GenAI Apps: Our Journey from Ideas to Production Excellence",Danil Topchii"GenAI Apps: Our Journey from Ideas to Production Excellence",Danil Topchii
"GenAI Apps: Our Journey from Ideas to Production Excellence",Danil Topchii
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
"What is a RAG system and how to build it",Dmytro Spodarets
"What is a RAG system and how to build it",Dmytro Spodarets"What is a RAG system and how to build it",Dmytro Spodarets
"What is a RAG system and how to build it",Dmytro Spodarets
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
"Distributed graphs and microservices in Prom.ua", Maksym Kindritskyi
"Distributed graphs and microservices in Prom.ua",  Maksym Kindritskyi"Distributed graphs and microservices in Prom.ua",  Maksym Kindritskyi
"Distributed graphs and microservices in Prom.ua", Maksym Kindritskyi
 
"Rethinking the existing data loading and processing process as an ETL exampl...
"Rethinking the existing data loading and processing process as an ETL exampl..."Rethinking the existing data loading and processing process as an ETL exampl...
"Rethinking the existing data loading and processing process as an ETL exampl...
 
"How Ukrainian IT specialist can go on vacation abroad without crossing the T...
"How Ukrainian IT specialist can go on vacation abroad without crossing the T..."How Ukrainian IT specialist can go on vacation abroad without crossing the T...
"How Ukrainian IT specialist can go on vacation abroad without crossing the T...
 
"The Strength of Being Vulnerable: the experience from CIA, Tesla and Uber", ...
"The Strength of Being Vulnerable: the experience from CIA, Tesla and Uber", ..."The Strength of Being Vulnerable: the experience from CIA, Tesla and Uber", ...
"The Strength of Being Vulnerable: the experience from CIA, Tesla and Uber", ...
 
"[QUICK TALK] Radical candor: how to achieve results faster thanks to a cultu...
"[QUICK TALK] Radical candor: how to achieve results faster thanks to a cultu..."[QUICK TALK] Radical candor: how to achieve results faster thanks to a cultu...
"[QUICK TALK] Radical candor: how to achieve results faster thanks to a cultu...
 
"[QUICK TALK] PDP Plan, the only one door to raise your salary and boost care...
"[QUICK TALK] PDP Plan, the only one door to raise your salary and boost care..."[QUICK TALK] PDP Plan, the only one door to raise your salary and boost care...
"[QUICK TALK] PDP Plan, the only one door to raise your salary and boost care...
 
"4 horsemen of the apocalypse of working relationships (+ antidotes to them)"...
"4 horsemen of the apocalypse of working relationships (+ antidotes to them)"..."4 horsemen of the apocalypse of working relationships (+ antidotes to them)"...
"4 horsemen of the apocalypse of working relationships (+ antidotes to them)"...
 
"Reconnecting with Purpose: Rediscovering Job Interest after Burnout", Anast...
"Reconnecting with Purpose: Rediscovering Job Interest after Burnout",  Anast..."Reconnecting with Purpose: Rediscovering Job Interest after Burnout",  Anast...
"Reconnecting with Purpose: Rediscovering Job Interest after Burnout", Anast...
 
"Mentoring 101: How to effectively invest experience in the success of others...
"Mentoring 101: How to effectively invest experience in the success of others..."Mentoring 101: How to effectively invest experience in the success of others...
"Mentoring 101: How to effectively invest experience in the success of others...
 
"Mission (im) possible: How to get an offer in 2024?", Oleksandra Myronova
"Mission (im) possible: How to get an offer in 2024?",  Oleksandra Myronova"Mission (im) possible: How to get an offer in 2024?",  Oleksandra Myronova
"Mission (im) possible: How to get an offer in 2024?", Oleksandra Myronova
 
"Why have we learned how to package products, but not how to 'package ourselv...
"Why have we learned how to package products, but not how to 'package ourselv..."Why have we learned how to package products, but not how to 'package ourselv...
"Why have we learned how to package products, but not how to 'package ourselv...
 
"How to tame the dragon, or leadership with imposter syndrome", Oleksandr Zin...
"How to tame the dragon, or leadership with imposter syndrome", Oleksandr Zin..."How to tame the dragon, or leadership with imposter syndrome", Oleksandr Zin...
"How to tame the dragon, or leadership with imposter syndrome", Oleksandr Zin...
 

Kürzlich hochgeladen

Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?XfilesPro
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhisoniya singh
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxOnBoard
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphNeo4j
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 

Kürzlich hochgeladen (20)

Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptx
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 

Антон Молдован "Type driven development with f#"

  • 1. TDD with F# (since 2003) Anton Moldovan (@antyadev) SBTech Twitter: https://twitter.com/antyaDev Github: https://github.com/antyaDev
  • 3.
  • 4.
  • 10.
  • 12. In OOP you by default thinking about abstraction extensibility
  • 13. In FP you by default thinking about purity composability correctness
  • 14. In FP you build your ideal, private world where you know everything
  • 16.
  • 17. If you are coming from an object-oriented design background, one of the paradigm shifts involved in "thinking functionally" is to change how you think about types. A well designed object-oriented program will have: • a strong focus on behavior rather than data, • will use a lot of polymorphism (interfaces), • will try to avoid having explicit knowledge of the actual concrete classes being passed around. A well designed functional program, on the other hand, will have a strong focus on data types rather than behavior
  • 18. type UserName = { firstName: string lastName: string } type Shape = | Circle of int | Rectangle of int * int
  • 19. type UserName = { firstName: string; lastName: string } let a = { firstName = "a"; lastName = "b" } let b = { firstName = "a"; lastName = "b" } if a = b then "equals" // true
  • 20. type Money = { amount: decimal currency: Currency } let a = { amount = 10; currency = USD } let b = { amount = 10; currency = USD } if a = b then "equals" // true
  • 21. type Shape = | Rectangle = 0 | Circle = 1 | Prism = 2
  • 22. type Shape = | Rectangle of width:float * length:float | Circle of radius:float | Prism of width:float * float * height:float let rectangle = Rectangle(width = 6.2, length = 5.5)
  • 23.
  • 24. anyone can set this to ‘true’ Rule 1: if the email is changed, the verified flag must be reset to ‘false’. Rule 2: the verified flag can only be set by a special verification service. Rule 3: we have 5 services which works only for verified email and 5 services which works for invalid email. class EmailContact { public string EmailAddress { get; set; } public bool IsEmailVerified { get; set; } }
  • 25. Rule 3: we have - 5 services which works only for verified email and - 5 services which works for invalid email. if (emailContract.IsEmailVerified) void SendEmailToApprove(EmailContact emailContract) { if (emailContract.IsEmailVerified) } void SendEmailToReject(EmailContact emailContract) { if (emailContract.IsEmailVerified) } void SendEmailToConfirm(EmailContact emailContract) { if (emailContract.IsEmailVerified) } void SendEmailToLinkedin(EmailContact emailContract) { if (emailContract.IsEmailVerified) }
  • 26. type ValidEmail = { email: string } type InvalidEmail = { email: string } type Email = | Valid of ValidEmail | Invalid of InvalidEmail let sendEmailToLinkedin (email: ValidEmail) = ... You need only one dispatch in one place
  • 27.
  • 29. public class NaiveShoppingCart<TItem> { private List<TItem> items; private decimal paidAmount; public NaiveShoppingCart() { this.items = new List<TItem>(); this.paidAmount = 0; } /// Is cart paid for? public bool IsPaidFor => this.paidAmount > 0; public IEnumerable<TItem> Items => this.items; public void AddItem(TItem item) { if (!this.IsPaidFor) this.items.Add(item); }
  • 30. if (!this.IsPaidFor) { do something }
  • 31. public class NaiveShoppingCart<TItem> { private List<TItem> items; public bool IsPaidFor => this.paidAmount > 0; public bool IsPaidFor => this.paidAmount > 0; public bool IsConfirmedByUser => _isConfirmedByUser; public bool IsApproved => IsPaidFor && _isValid; public bool IsCanceledByUser => _isCanceled && _user != null; public bool IsCanceledAuto => _isCanceled || _user == null && _system != null; public bool IsCanceledAdmin => _isCanceled || _user == null && _system == null && _admin != null; public Status GetStatus() { if (_isCanceled && items.Count > 0) return Status.Invalid; else if (items.Count > 0) return Status.Active; return Status.Empty; } public void Approve() { if (_isCanceled) throw new Exception(); if (items.Count > 0) } what about recently added IsCanceledByAdmin?
  • 32.
  • 34. type CartItem = string // placeholder for a more complicated type type EmptyState = NoItems type ActiveState = { unpaidItems: CartItem list; } type PaidForState = { paidItems: CartItem list; payment: decimal} type Cart = | Empty of EmptyState | Active of ActiveState | PaidFor of PaidForState
  • 35. type EmptyState = NoItems type ActiveState = { unpaidItems: CartItem list; } type PaidForState = { paidItems: CartItem list; payment: decimal } type Cart = | Empty of EmptyState | Active of ActiveState | PaidFor of PaidForState // ============================= // operations on empty state // ============================= let addToEmptyState (item: CartItem) : Cart.Active = Cart.Active { unpaidItems = [item] } // a new Active Cart
  • 36. type EmptyState = NoItems type ActiveState = { unpaidItems: CartItem list; } type PaidForState = { paidItems: CartItem list; payment: decimal } type Cart = | Empty of EmptyState | Active of ActiveState | PaidFor of PaidForState // ============================= // operation on empty state // ============================= let addToEmptyState item = { unpaidItems = [item] } // returns a new Active Cart
  • 37. type EmptyState = NoItems type ActiveState = { unpaidItems: CartItem list; } type PaidForState = { paidItems: CartItem list; payment: decimal } type Cart = | Empty of EmptyState | Active of ActiveState | PaidFor of PaidForState // ============================= // operation on active state // ============================= let addToActiveState (state: ActiveState, itemToAdd: CartItem) = let newList = itemToAdd :: state.unpaidItems Cart.Active { state with unpaidItems = newList }
  • 38. type EmptyState = NoItems type ActiveState = { unpaidItems: CartItem list; } type PaidForState = { paidItems: CartItem list; payment: decimal } type Cart = | Empty of EmptyState | Active of ActiveState | PaidFor of PaidForState // ============================= // operation on active state // ============================= let addToActiveState state itemToAdd = let newList = itemToAdd :: state.unpaidItems { state with unpaidItems = newList }
  • 39. type EmptyState = NoItems type ActiveState = { unpaidItems: CartItem list; } type PaidForState = { paidItems: CartItem list; payment: decimal } type Cart = | Empty of EmptyState | Active of ActiveState | PaidFor of PaidForState let removeFromActiveState state itemToRemove = let newList = state.unpaidItems |> List.filter (fun i -> i <> itemToRemove) match newList with | [] -> Cart.Empty NoItems | _ -> Cart.Active { state with unpaidItems = newList }
  • 40. type EmptyState = NoItems type ActiveState = { unpaidItems: CartItem list; } type PaidForState = { paidItems: CartItem list; payment: decimal } type Cart = | Empty of EmptyState | Active of ActiveState | PaidFor of PaidForState let payForActiveState state amount = Cart.PaidFor { paidItems = state.unpaidItems payment = amount }
  • 41. type EmptyState = NoItems type ActiveState = { unpaidItems: CartItem list; } type PaidForState = { paidItems: CartItem list; payment: decimal} type Cart = | Empty of EmptyState | Active of ActiveState | PaidFor of PaidForState let item = “test_product” let activeState = addToEmptyState(item) let paidState = payForActiveState(activeState, 10) // compile error, your state is not active anymore let activeState = addToActiveState(paidState, item)
  • 43. let failingFunc num = let x = raise (new System.Exception("fail!")) try let y = 42 + 5 + num x + y with e -> 43
  • 44. /// Represents the result of a computation type Result<'ok, 'msg> = | Ok of 'ok * 'msg list | Fail of 'msg list
  • 45. type Request = { name: string; email: string } let validateInput input = if input.name = "" then Fail("Name must not be blank") elif input.email = "" then Fail("Email must not be blank") else Ok(input)
  • 46. type Request = { name: string; email: string } let validateInput input = if input.name = "" then fail "Name must not be blank" elif input.email = "" then fail "Email must not be blank" else ok input
  • 47. let validate1 input = if input.name = "" then fail "Name must not be blank“ else ok input let validate2 input = if input.name.Length > 50 then fail "Name must not be longer than 50 chars" else ok input let validate3 input = if input.email = "" then fail "Email must not be blank" else ok input let validRequest = validate1 >>= validate2 >>= validate3 >>= validate4
  • 48.
  • 49. In functional programming we strive to write side-effect free applications. In other words, all the functions of the application should be pure. However, completely side-effect free applications are mostly useless, so the next best thing is to minimize the amount of side-effects, make them explicit and push them as close to the boundaries of the application as possible.
  • 50. Let’s see an example in invoicing domain. When changing a due date of an invoice we want to check that the new due date is in the future. We could implement it like this: let changeDueDate (newDueDate:DateTime, invoice) = if newDueDate > System.DateTime.Today then ok { invoice with dueDate = newDueDate } else fail "Due date must be in future."
  • 51. let changeDueDate (newDueDate:DateTime, currentDate:DateTime, invoice) = if newDueDate > currentDate then ok { invoice with dueDate = newDueDate } else fail "Due date must be in future."
  • 52. type PastDate = PastDate of DateTime type CurrentDate = CurrentDate of DateTime type FutureDate = FutureDate of DateTime type Date = | Past of PastDate | Current of CurrentDate | Future of FutureDate let changeDueDate (newDueDate:FutureDate, invoice) = { invoice with DueDate = Date newDueDate }
  • 53. Problem: Language do not integrate information - We need to bring information into the language…