SlideShare a Scribd company logo
Hand Rolled Applicative
User Validation
Code Kata
<*> AKA tie-fighter, apply, ap
*> AKA right-facing bird, right shark
User Validation
Program
@philip_schwarz
slides by http://fpilluminated.com/
Could you use a simple piece of Scala validation code (granted, a very simplistic one too!) that you can
rewrite, now and again, to refresh your basic understanding of Applicative operators <*>, <*, *>?
The goal is not to write perfect code showcasing validation, but rather, to provide a small, rough-and
ready exercise to reinforce your muscle-memory.
Despite its grandiose-sounding title, this deck consists of just three slides showing the Scala 3 code to be
rewritten whenever the details of the operators begin to fade away.
The code is my rough and ready translation of a Haskell user-validation program found in a book called
Finding Success (and Failure) in Haskell - Fall in love with applicative functors.
@philip_schwarz
trait Semigroup[A]:
extension (lhs: A)
def <>(rhs: A): A
trait Functor[F[_]]:
extension [A](fa: F[A])
def map[B](f: A => B): F[B]
trait Applicative[F[_]] extends Functor[F]:
def unit[A](a: => A): F[A]
extension [A](fa: F[A])
def map[B](f: A => B): F[B] = unit(f) <*> fa
extension [A,B](fab: F[A => B])
def <*>(fa: F[A]): F[B]
extension [A,B](fa: F[A])
def *>(fb: F[B]): F[B]
def <*(fb: F[B]): F[A]
case class Username(username: String)
case class Password(password: String)
case class User(username: Username, password: Password)
case class Error(errors: List[String])
enum Validation[+E, +A]:
case Failure(errors: E)
case Success(a: A)
given Semigroup[Error] = new Semigroup[Error]:
extension (lhs: Error)
def <>(rhs: Error): Error =
Error(lhs.errors ++ rhs.errors)
given (using Semigroup[Error]): Applicative[[X] =>> Validation[Error, X]] =
new Applicative[[X] =>> Validation[Error, X]]:
override def unit[A](a: => A): Validation[Error, A] = Success(a)
extension [A, B](fab: Validation[Error, A => B])
override def <*>(fa: Validation[Error, A]): Validation[Error, B] = (fab, fa) match
case (Success(ab), Success(a)) => Success(ab(a))
case (Failure(e1), Failure(e2)) => Failure(e1 <> e2)
case (Failure(e), _) => Failure(e)
case (_, Failure(e)) => Failure(e)
extension [A, B](fa: Validation[Error, A])
override def *>(fb: Validation[Error, B]): Validation[Error, B] = (fa, fb) match
case (Failure(e1), Failure(e2)) => Failure(e1 <> e2)
case (Failure(e), _) => Failure(e)
case _ => fb
override def <*(fb: Validation[Error, B]): Validation[Error, A] = (fa, fb) match
case (Failure(e1), Failure(e2)) => Failure(e1 <> e2)
case (_, Failure(e)) => Failure(e)
case _ => fa
def checkUsernameLength(username: String): Validation[Error, Username] =
if username.length <= 15
then Success(Username(username))
else Failure(Error(List("Your username cannot be longer than 15 characters.")))
def checkPasswordLength(password: String): Validation[Error, Password] =
if password.length <= 20
then Success(Password(password))
else Failure(Error(List("Your password cannot be longer than 20 characters.")))
def requireAlphaNumeric(input: String): Validation[Error, String] =
if input.forall(_.isLetterOrDigit)
then Success(input)
else Failure(Error(List("Cannot contain whitespace or special characters.")))
def cleanWhiteSpace(input: String): Validation[Error, String] =
input.dropWhile(_.isWhitespace) match
case "" => Failure(Error(List("Cannot be empty.")))
case cleaned => Success(cleaned)
def validateUsername(username: Username): Validation[Error, Username] = username match
case Username(usr) =>
cleanWhiteSpace(usr) match
case Failure(error) => Failure(error)
case Success(cleanedUsername) => requireAlphaNumeric(cleanedUsername) *> checkUsernameLength(cleanedUsername)
def validatePassword(password: Password): Validation[Error, Password] = password match
case Password(pwd) =>
cleanWhiteSpace(pwd) match
case Failure(error) => Failure(error)
case Success(cleanedPassword) => requireAlphaNumeric(cleanedPassword) *> checkPasswordLength(cleanedPassword)
def makeUser(userName: Username, password: Password): Validation[Error, User] =
validateUsername(userName).map(User.apply.curried) <*> validatePassword(password)
@main
def main(): Unit =
assert(makeUser(Username("FredSmith"), Password("pa22w0rd")) == Success(User(Username("FredSmith"), Password("pa22w0rd"))))
assert(makeUser(Username("Fred$Smith"), Password("pa22w0rd")) == Failure(Error(List("Cannot contain whitespace or special characters."))))
assert(makeUser(Username("FredSmith"), Password("pa22w*rd")) == Failure(Error(List("Cannot contain whitespace or special characters."))))
assert(makeUser(Username("overlongusername"), Password("pa22w0rd")) == Failure(Error(List("Your username cannot be longer than 15 characters."))))
assert(makeUser(Username("FredSmith"), Password("averyverylongpassword")) == Failure(Error(List("Your password cannot be longer than 20 characters."))))
assert(
makeUser(Username("overlong#username"), Password("averyverylongpassword"))
==
Failure(Error(List(
"Cannot contain whitespace or special characters.",
"Your username cannot be longer than 15 characters.",
"Your password cannot be longer than 20 characters.")))
)

More Related Content

Similar to Hand Rolled Applicative User Validation Code Kata

Beginning Scala Svcc 2009
Beginning Scala Svcc 2009Beginning Scala Svcc 2009
Beginning Scala Svcc 2009
David Pollak
 
Decent exposure: Controladores sin @ivars
Decent exposure: Controladores sin @ivarsDecent exposure: Controladores sin @ivars
Decent exposure: Controladores sin @ivars
Leonardo Soto
 
Auto testing!
Auto testing!Auto testing!
Auto testing!
Kwangsoo Shin
 
Es6 to es5
Es6 to es5Es6 to es5
Es6 to es5
Shakhzod Tojiyev
 
How To Test Everything
How To Test EverythingHow To Test Everything
How To Test Everything
noelrap
 
Idiomatic Javascript (ES5 to ES2015+)
Idiomatic Javascript (ES5 to ES2015+)Idiomatic Javascript (ES5 to ES2015+)
Idiomatic Javascript (ES5 to ES2015+)
David Atchley
 
Principled Error Handling - Scalapeño
Principled Error Handling - ScalapeñoPrincipled Error Handling - Scalapeño
Principled Error Handling - Scalapeño
Luka Jacobowitz
 
Refactor like a boss
Refactor like a bossRefactor like a boss
Refactor like a boss
gsterndale
 
Re-Design with Elixir/OTP
Re-Design with Elixir/OTPRe-Design with Elixir/OTP
Re-Design with Elixir/OTP
Mustafa TURAN
 
Say Goodbye to Procedural Programming - Nick Sutterer
Say Goodbye to Procedural Programming - Nick SuttererSay Goodbye to Procedural Programming - Nick Sutterer
Say Goodbye to Procedural Programming - Nick Sutterer
Ruby Meditation
 
Funkcija, objekt, python
Funkcija, objekt, pythonFunkcija, objekt, python
Funkcija, objekt, python
Robert Lujo
 
ES6: The future is now
ES6: The future is nowES6: The future is now
ES6: The future is now
Sebastiano Armeli
 
SCULPT! YOUR! TESTS!
SCULPT! YOUR! TESTS!SCULPT! YOUR! TESTS!
SCULPT! YOUR! TESTS!
Taras Oleksyn
 
T3chFest 2016 - The polyglot programmer
T3chFest 2016 - The polyglot programmerT3chFest 2016 - The polyglot programmer
T3chFest 2016 - The polyglot programmer
David Muñoz Díaz
 
Fp in scala part 2
Fp in scala part 2Fp in scala part 2
Fp in scala part 2
Hang Zhao
 
Painless Javascript Unit Testing
Painless Javascript Unit TestingPainless Javascript Unit Testing
Painless Javascript Unit Testing
Benjamin Wilson
 
Javaz. Functional design in Java 8.
Javaz. Functional design in Java 8.Javaz. Functional design in Java 8.
Javaz. Functional design in Java 8.
Vadim Dubs
 
Phoenix for laravel developers
Phoenix for laravel developersPhoenix for laravel developers
Phoenix for laravel developers
Luiz Messias
 
PHP Workshop Notes
PHP Workshop NotesPHP Workshop Notes
PHP Workshop Notes
Pamela Fox
 
Functional programming in ruby
Functional programming in rubyFunctional programming in ruby
Functional programming in ruby
Koen Handekyn
 

Similar to Hand Rolled Applicative User Validation Code Kata (20)

Beginning Scala Svcc 2009
Beginning Scala Svcc 2009Beginning Scala Svcc 2009
Beginning Scala Svcc 2009
 
Decent exposure: Controladores sin @ivars
Decent exposure: Controladores sin @ivarsDecent exposure: Controladores sin @ivars
Decent exposure: Controladores sin @ivars
 
Auto testing!
Auto testing!Auto testing!
Auto testing!
 
Es6 to es5
Es6 to es5Es6 to es5
Es6 to es5
 
How To Test Everything
How To Test EverythingHow To Test Everything
How To Test Everything
 
Idiomatic Javascript (ES5 to ES2015+)
Idiomatic Javascript (ES5 to ES2015+)Idiomatic Javascript (ES5 to ES2015+)
Idiomatic Javascript (ES5 to ES2015+)
 
Principled Error Handling - Scalapeño
Principled Error Handling - ScalapeñoPrincipled Error Handling - Scalapeño
Principled Error Handling - Scalapeño
 
Refactor like a boss
Refactor like a bossRefactor like a boss
Refactor like a boss
 
Re-Design with Elixir/OTP
Re-Design with Elixir/OTPRe-Design with Elixir/OTP
Re-Design with Elixir/OTP
 
Say Goodbye to Procedural Programming - Nick Sutterer
Say Goodbye to Procedural Programming - Nick SuttererSay Goodbye to Procedural Programming - Nick Sutterer
Say Goodbye to Procedural Programming - Nick Sutterer
 
Funkcija, objekt, python
Funkcija, objekt, pythonFunkcija, objekt, python
Funkcija, objekt, python
 
ES6: The future is now
ES6: The future is nowES6: The future is now
ES6: The future is now
 
SCULPT! YOUR! TESTS!
SCULPT! YOUR! TESTS!SCULPT! YOUR! TESTS!
SCULPT! YOUR! TESTS!
 
T3chFest 2016 - The polyglot programmer
T3chFest 2016 - The polyglot programmerT3chFest 2016 - The polyglot programmer
T3chFest 2016 - The polyglot programmer
 
Fp in scala part 2
Fp in scala part 2Fp in scala part 2
Fp in scala part 2
 
Painless Javascript Unit Testing
Painless Javascript Unit TestingPainless Javascript Unit Testing
Painless Javascript Unit Testing
 
Javaz. Functional design in Java 8.
Javaz. Functional design in Java 8.Javaz. Functional design in Java 8.
Javaz. Functional design in Java 8.
 
Phoenix for laravel developers
Phoenix for laravel developersPhoenix for laravel developers
Phoenix for laravel developers
 
PHP Workshop Notes
PHP Workshop NotesPHP Workshop Notes
PHP Workshop Notes
 
Functional programming in ruby
Functional programming in rubyFunctional programming in ruby
Functional programming in ruby
 

More from Philip Schwarz

Folding Cheat Sheet #6 - sixth in a series
Folding Cheat Sheet #6 - sixth in a seriesFolding Cheat Sheet #6 - sixth in a series
Folding Cheat Sheet #6 - sixth in a series
Philip Schwarz
 
Folding Cheat Sheet #5 - fifth in a series
Folding Cheat Sheet #5 - fifth in a seriesFolding Cheat Sheet #5 - fifth in a series
Folding Cheat Sheet #5 - fifth in a series
Philip Schwarz
 
A Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of PassageA Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of Passage
Philip Schwarz
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Philip Schwarz
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a series
Philip Schwarz
 
Folding Cheat Sheet #3 - third in a series
Folding Cheat Sheet #3 - third in a seriesFolding Cheat Sheet #3 - third in a series
Folding Cheat Sheet #3 - third in a series
Philip Schwarz
 
Folding Cheat Sheet #2 - second in a series
Folding Cheat Sheet #2 - second in a seriesFolding Cheat Sheet #2 - second in a series
Folding Cheat Sheet #2 - second in a series
Philip Schwarz
 
Folding Cheat Sheet #1 - first in a series
Folding Cheat Sheet #1 - first in a seriesFolding Cheat Sheet #1 - first in a series
Folding Cheat Sheet #1 - first in a series
Philip Schwarz
 
Scala Left Fold Parallelisation - Three Approaches
Scala Left Fold Parallelisation- Three ApproachesScala Left Fold Parallelisation- Three Approaches
Scala Left Fold Parallelisation - Three Approaches
Philip Schwarz
 
Tagless Final Encoding - Algebras and Interpreters and also Programs
Tagless Final Encoding - Algebras and Interpreters and also ProgramsTagless Final Encoding - Algebras and Interpreters and also Programs
Tagless Final Encoding - Algebras and Interpreters and also Programs
Philip Schwarz
 
Fusing Transformations of Strict Scala Collections with Views
Fusing Transformations of Strict Scala Collections with ViewsFusing Transformations of Strict Scala Collections with Views
Fusing Transformations of Strict Scala Collections with Views
Philip Schwarz
 
A sighting of traverse_ function in Practical FP in Scala
A sighting of traverse_ function in Practical FP in ScalaA sighting of traverse_ function in Practical FP in Scala
A sighting of traverse_ function in Practical FP in Scala
Philip Schwarz
 
A sighting of traverseFilter and foldMap in Practical FP in Scala
A sighting of traverseFilter and foldMap in Practical FP in ScalaA sighting of traverseFilter and foldMap in Practical FP in Scala
A sighting of traverseFilter and foldMap in Practical FP in Scala
Philip Schwarz
 
A sighting of sequence function in Practical FP in Scala
A sighting of sequence function in Practical FP in ScalaA sighting of sequence function in Practical FP in Scala
A sighting of sequence function in Practical FP in Scala
Philip Schwarz
 
N-Queens Combinatorial Puzzle meets Cats
N-Queens Combinatorial Puzzle meets CatsN-Queens Combinatorial Puzzle meets Cats
N-Queens Combinatorial Puzzle meets Cats
Philip Schwarz
 
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
Philip Schwarz
 
The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...
Philip Schwarz
 
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Nat, List and Option Monoids -from scratch -Combining and Folding -an exampleNat, List and Option Monoids -from scratch -Combining and Folding -an example
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Philip Schwarz
 
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Nat, List and Option Monoids -from scratch -Combining and Folding -an exampleNat, List and Option Monoids -from scratch -Combining and Folding -an example
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Philip Schwarz
 
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
Philip Schwarz
 

More from Philip Schwarz (20)

Folding Cheat Sheet #6 - sixth in a series
Folding Cheat Sheet #6 - sixth in a seriesFolding Cheat Sheet #6 - sixth in a series
Folding Cheat Sheet #6 - sixth in a series
 
Folding Cheat Sheet #5 - fifth in a series
Folding Cheat Sheet #5 - fifth in a seriesFolding Cheat Sheet #5 - fifth in a series
Folding Cheat Sheet #5 - fifth in a series
 
A Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of PassageA Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of Passage
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a series
 
Folding Cheat Sheet #3 - third in a series
Folding Cheat Sheet #3 - third in a seriesFolding Cheat Sheet #3 - third in a series
Folding Cheat Sheet #3 - third in a series
 
Folding Cheat Sheet #2 - second in a series
Folding Cheat Sheet #2 - second in a seriesFolding Cheat Sheet #2 - second in a series
Folding Cheat Sheet #2 - second in a series
 
Folding Cheat Sheet #1 - first in a series
Folding Cheat Sheet #1 - first in a seriesFolding Cheat Sheet #1 - first in a series
Folding Cheat Sheet #1 - first in a series
 
Scala Left Fold Parallelisation - Three Approaches
Scala Left Fold Parallelisation- Three ApproachesScala Left Fold Parallelisation- Three Approaches
Scala Left Fold Parallelisation - Three Approaches
 
Tagless Final Encoding - Algebras and Interpreters and also Programs
Tagless Final Encoding - Algebras and Interpreters and also ProgramsTagless Final Encoding - Algebras and Interpreters and also Programs
Tagless Final Encoding - Algebras and Interpreters and also Programs
 
Fusing Transformations of Strict Scala Collections with Views
Fusing Transformations of Strict Scala Collections with ViewsFusing Transformations of Strict Scala Collections with Views
Fusing Transformations of Strict Scala Collections with Views
 
A sighting of traverse_ function in Practical FP in Scala
A sighting of traverse_ function in Practical FP in ScalaA sighting of traverse_ function in Practical FP in Scala
A sighting of traverse_ function in Practical FP in Scala
 
A sighting of traverseFilter and foldMap in Practical FP in Scala
A sighting of traverseFilter and foldMap in Practical FP in ScalaA sighting of traverseFilter and foldMap in Practical FP in Scala
A sighting of traverseFilter and foldMap in Practical FP in Scala
 
A sighting of sequence function in Practical FP in Scala
A sighting of sequence function in Practical FP in ScalaA sighting of sequence function in Practical FP in Scala
A sighting of sequence function in Practical FP in Scala
 
N-Queens Combinatorial Puzzle meets Cats
N-Queens Combinatorial Puzzle meets CatsN-Queens Combinatorial Puzzle meets Cats
N-Queens Combinatorial Puzzle meets Cats
 
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
 
The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...
 
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Nat, List and Option Monoids -from scratch -Combining and Folding -an exampleNat, List and Option Monoids -from scratch -Combining and Folding -an example
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
 
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Nat, List and Option Monoids -from scratch -Combining and Folding -an exampleNat, List and Option Monoids -from scratch -Combining and Folding -an example
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
 
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
 

Recently uploaded

Streamlining End-to-End Testing Automation
Streamlining End-to-End Testing AutomationStreamlining End-to-End Testing Automation
Streamlining End-to-End Testing Automation
Anand Bagmar
 
Upturn India Technologies - Web development company in Nashik
Upturn India Technologies - Web development company in NashikUpturn India Technologies - Web development company in Nashik
Upturn India Technologies - Web development company in Nashik
Upturn India Technologies
 
Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...
Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...
Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...
The Third Creative Media
 
How GenAI Can Improve Supplier Performance Management.pdf
How GenAI Can Improve Supplier Performance Management.pdfHow GenAI Can Improve Supplier Performance Management.pdf
How GenAI Can Improve Supplier Performance Management.pdf
Zycus
 
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Paul Brebner
 
Hands-on with Apache Druid: Installation & Data Ingestion Steps
Hands-on with Apache Druid: Installation & Data Ingestion StepsHands-on with Apache Druid: Installation & Data Ingestion Steps
Hands-on with Apache Druid: Installation & Data Ingestion Steps
servicesNitor
 
Refactoring legacy systems using events commands and bubble contexts
Refactoring legacy systems using events commands and bubble contextsRefactoring legacy systems using events commands and bubble contexts
Refactoring legacy systems using events commands and bubble contexts
Michał Kurzeja
 
Enhanced Screen Flows UI/UX using SLDS with Tom Kitt
Enhanced Screen Flows UI/UX using SLDS with Tom KittEnhanced Screen Flows UI/UX using SLDS with Tom Kitt
Enhanced Screen Flows UI/UX using SLDS with Tom Kitt
Peter Caitens
 
Microsoft-Power-Platform-Adoption-Planning.pptx
Microsoft-Power-Platform-Adoption-Planning.pptxMicrosoft-Power-Platform-Adoption-Planning.pptx
Microsoft-Power-Platform-Adoption-Planning.pptx
jrodriguezq3110
 
Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)
Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)
Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)
safelyiotech
 
What is Continuous Testing in DevOps - A Definitive Guide.pdf
What is Continuous Testing in DevOps - A Definitive Guide.pdfWhat is Continuous Testing in DevOps - A Definitive Guide.pdf
What is Continuous Testing in DevOps - A Definitive Guide.pdf
kalichargn70th171
 
Strengthening Web Development with CommandBox 6: Seamless Transition and Scal...
Strengthening Web Development with CommandBox 6: Seamless Transition and Scal...Strengthening Web Development with CommandBox 6: Seamless Transition and Scal...
Strengthening Web Development with CommandBox 6: Seamless Transition and Scal...
Ortus Solutions, Corp
 
Flutter vs. React Native: A Detailed Comparison for App Development in 2024
Flutter vs. React Native: A Detailed Comparison for App Development in 2024Flutter vs. React Native: A Detailed Comparison for App Development in 2024
Flutter vs. React Native: A Detailed Comparison for App Development in 2024
dhavalvaghelanectarb
 
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSISDECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
Tier1 app
 
The Comprehensive Guide to Validating Audio-Visual Performances.pdf
The Comprehensive Guide to Validating Audio-Visual Performances.pdfThe Comprehensive Guide to Validating Audio-Visual Performances.pdf
The Comprehensive Guide to Validating Audio-Visual Performances.pdf
kalichargn70th171
 
Superpower Your Apache Kafka Applications Development with Complementary Open...
Superpower Your Apache Kafka Applications Development with Complementary Open...Superpower Your Apache Kafka Applications Development with Complementary Open...
Superpower Your Apache Kafka Applications Development with Complementary Open...
Paul Brebner
 
Orca: Nocode Graphical Editor for Container Orchestration
Orca: Nocode Graphical Editor for Container OrchestrationOrca: Nocode Graphical Editor for Container Orchestration
Orca: Nocode Graphical Editor for Container Orchestration
Pedro J. Molina
 
What’s New in VictoriaLogs - Q2 2024 Update
What’s New in VictoriaLogs - Q2 2024 UpdateWhat’s New in VictoriaLogs - Q2 2024 Update
What’s New in VictoriaLogs - Q2 2024 Update
VictoriaMetrics
 
Going AOT: Everything you need to know about GraalVM for Java applications
Going AOT: Everything you need to know about GraalVM for Java applicationsGoing AOT: Everything you need to know about GraalVM for Java applications
Going AOT: Everything you need to know about GraalVM for Java applications
Alina Yurenko
 

Recently uploaded (20)

Streamlining End-to-End Testing Automation
Streamlining End-to-End Testing AutomationStreamlining End-to-End Testing Automation
Streamlining End-to-End Testing Automation
 
Upturn India Technologies - Web development company in Nashik
Upturn India Technologies - Web development company in NashikUpturn India Technologies - Web development company in Nashik
Upturn India Technologies - Web development company in Nashik
 
Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...
Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...
Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...
 
How GenAI Can Improve Supplier Performance Management.pdf
How GenAI Can Improve Supplier Performance Management.pdfHow GenAI Can Improve Supplier Performance Management.pdf
How GenAI Can Improve Supplier Performance Management.pdf
 
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
 
Hands-on with Apache Druid: Installation & Data Ingestion Steps
Hands-on with Apache Druid: Installation & Data Ingestion StepsHands-on with Apache Druid: Installation & Data Ingestion Steps
Hands-on with Apache Druid: Installation & Data Ingestion Steps
 
Refactoring legacy systems using events commands and bubble contexts
Refactoring legacy systems using events commands and bubble contextsRefactoring legacy systems using events commands and bubble contexts
Refactoring legacy systems using events commands and bubble contexts
 
Enhanced Screen Flows UI/UX using SLDS with Tom Kitt
Enhanced Screen Flows UI/UX using SLDS with Tom KittEnhanced Screen Flows UI/UX using SLDS with Tom Kitt
Enhanced Screen Flows UI/UX using SLDS with Tom Kitt
 
Microsoft-Power-Platform-Adoption-Planning.pptx
Microsoft-Power-Platform-Adoption-Planning.pptxMicrosoft-Power-Platform-Adoption-Planning.pptx
Microsoft-Power-Platform-Adoption-Planning.pptx
 
Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)
Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)
Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)
 
What is Continuous Testing in DevOps - A Definitive Guide.pdf
What is Continuous Testing in DevOps - A Definitive Guide.pdfWhat is Continuous Testing in DevOps - A Definitive Guide.pdf
What is Continuous Testing in DevOps - A Definitive Guide.pdf
 
Strengthening Web Development with CommandBox 6: Seamless Transition and Scal...
Strengthening Web Development with CommandBox 6: Seamless Transition and Scal...Strengthening Web Development with CommandBox 6: Seamless Transition and Scal...
Strengthening Web Development with CommandBox 6: Seamless Transition and Scal...
 
Flutter vs. React Native: A Detailed Comparison for App Development in 2024
Flutter vs. React Native: A Detailed Comparison for App Development in 2024Flutter vs. React Native: A Detailed Comparison for App Development in 2024
Flutter vs. React Native: A Detailed Comparison for App Development in 2024
 
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSISDECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
 
The Comprehensive Guide to Validating Audio-Visual Performances.pdf
The Comprehensive Guide to Validating Audio-Visual Performances.pdfThe Comprehensive Guide to Validating Audio-Visual Performances.pdf
The Comprehensive Guide to Validating Audio-Visual Performances.pdf
 
bgiolcb
bgiolcbbgiolcb
bgiolcb
 
Superpower Your Apache Kafka Applications Development with Complementary Open...
Superpower Your Apache Kafka Applications Development with Complementary Open...Superpower Your Apache Kafka Applications Development with Complementary Open...
Superpower Your Apache Kafka Applications Development with Complementary Open...
 
Orca: Nocode Graphical Editor for Container Orchestration
Orca: Nocode Graphical Editor for Container OrchestrationOrca: Nocode Graphical Editor for Container Orchestration
Orca: Nocode Graphical Editor for Container Orchestration
 
What’s New in VictoriaLogs - Q2 2024 Update
What’s New in VictoriaLogs - Q2 2024 UpdateWhat’s New in VictoriaLogs - Q2 2024 Update
What’s New in VictoriaLogs - Q2 2024 Update
 
Going AOT: Everything you need to know about GraalVM for Java applications
Going AOT: Everything you need to know about GraalVM for Java applicationsGoing AOT: Everything you need to know about GraalVM for Java applications
Going AOT: Everything you need to know about GraalVM for Java applications
 

Hand Rolled Applicative User Validation Code Kata

  • 1. Hand Rolled Applicative User Validation Code Kata <*> AKA tie-fighter, apply, ap *> AKA right-facing bird, right shark User Validation Program @philip_schwarz slides by http://fpilluminated.com/
  • 2. Could you use a simple piece of Scala validation code (granted, a very simplistic one too!) that you can rewrite, now and again, to refresh your basic understanding of Applicative operators <*>, <*, *>? The goal is not to write perfect code showcasing validation, but rather, to provide a small, rough-and ready exercise to reinforce your muscle-memory. Despite its grandiose-sounding title, this deck consists of just three slides showing the Scala 3 code to be rewritten whenever the details of the operators begin to fade away. The code is my rough and ready translation of a Haskell user-validation program found in a book called Finding Success (and Failure) in Haskell - Fall in love with applicative functors. @philip_schwarz
  • 3. trait Semigroup[A]: extension (lhs: A) def <>(rhs: A): A trait Functor[F[_]]: extension [A](fa: F[A]) def map[B](f: A => B): F[B] trait Applicative[F[_]] extends Functor[F]: def unit[A](a: => A): F[A] extension [A](fa: F[A]) def map[B](f: A => B): F[B] = unit(f) <*> fa extension [A,B](fab: F[A => B]) def <*>(fa: F[A]): F[B] extension [A,B](fa: F[A]) def *>(fb: F[B]): F[B] def <*(fb: F[B]): F[A] case class Username(username: String) case class Password(password: String) case class User(username: Username, password: Password) case class Error(errors: List[String]) enum Validation[+E, +A]: case Failure(errors: E) case Success(a: A) given Semigroup[Error] = new Semigroup[Error]: extension (lhs: Error) def <>(rhs: Error): Error = Error(lhs.errors ++ rhs.errors) given (using Semigroup[Error]): Applicative[[X] =>> Validation[Error, X]] = new Applicative[[X] =>> Validation[Error, X]]: override def unit[A](a: => A): Validation[Error, A] = Success(a) extension [A, B](fab: Validation[Error, A => B]) override def <*>(fa: Validation[Error, A]): Validation[Error, B] = (fab, fa) match case (Success(ab), Success(a)) => Success(ab(a)) case (Failure(e1), Failure(e2)) => Failure(e1 <> e2) case (Failure(e), _) => Failure(e) case (_, Failure(e)) => Failure(e) extension [A, B](fa: Validation[Error, A]) override def *>(fb: Validation[Error, B]): Validation[Error, B] = (fa, fb) match case (Failure(e1), Failure(e2)) => Failure(e1 <> e2) case (Failure(e), _) => Failure(e) case _ => fb override def <*(fb: Validation[Error, B]): Validation[Error, A] = (fa, fb) match case (Failure(e1), Failure(e2)) => Failure(e1 <> e2) case (_, Failure(e)) => Failure(e) case _ => fa
  • 4. def checkUsernameLength(username: String): Validation[Error, Username] = if username.length <= 15 then Success(Username(username)) else Failure(Error(List("Your username cannot be longer than 15 characters."))) def checkPasswordLength(password: String): Validation[Error, Password] = if password.length <= 20 then Success(Password(password)) else Failure(Error(List("Your password cannot be longer than 20 characters."))) def requireAlphaNumeric(input: String): Validation[Error, String] = if input.forall(_.isLetterOrDigit) then Success(input) else Failure(Error(List("Cannot contain whitespace or special characters."))) def cleanWhiteSpace(input: String): Validation[Error, String] = input.dropWhile(_.isWhitespace) match case "" => Failure(Error(List("Cannot be empty."))) case cleaned => Success(cleaned) def validateUsername(username: Username): Validation[Error, Username] = username match case Username(usr) => cleanWhiteSpace(usr) match case Failure(error) => Failure(error) case Success(cleanedUsername) => requireAlphaNumeric(cleanedUsername) *> checkUsernameLength(cleanedUsername) def validatePassword(password: Password): Validation[Error, Password] = password match case Password(pwd) => cleanWhiteSpace(pwd) match case Failure(error) => Failure(error) case Success(cleanedPassword) => requireAlphaNumeric(cleanedPassword) *> checkPasswordLength(cleanedPassword) def makeUser(userName: Username, password: Password): Validation[Error, User] = validateUsername(userName).map(User.apply.curried) <*> validatePassword(password)
  • 5. @main def main(): Unit = assert(makeUser(Username("FredSmith"), Password("pa22w0rd")) == Success(User(Username("FredSmith"), Password("pa22w0rd")))) assert(makeUser(Username("Fred$Smith"), Password("pa22w0rd")) == Failure(Error(List("Cannot contain whitespace or special characters.")))) assert(makeUser(Username("FredSmith"), Password("pa22w*rd")) == Failure(Error(List("Cannot contain whitespace or special characters.")))) assert(makeUser(Username("overlongusername"), Password("pa22w0rd")) == Failure(Error(List("Your username cannot be longer than 15 characters.")))) assert(makeUser(Username("FredSmith"), Password("averyverylongpassword")) == Failure(Error(List("Your password cannot be longer than 20 characters.")))) assert( makeUser(Username("overlong#username"), Password("averyverylongpassword")) == Failure(Error(List( "Cannot contain whitespace or special characters.", "Your username cannot be longer than 15 characters.", "Your password cannot be longer than 20 characters."))) )