SlideShare a Scribd company logo
First-Class Patterns
John A. De Goes - @jdegoes
Frontier Developers, February 26
Agenda
●
●
●
●
●
●

Intro
Pattern Matching 101
First-Class-ness 101
Magical Patterns
First-Class Patterns
Exercises
Intro
Pattern Matching
● Divides a (possibly infinite) set of values into
a discrete number of cases, where each case
can be handled in a uniform way
● “if” on steroids
○ Sometimes strictly more powerful (e.g. Haskell)
Intro - Examples
-- sign of a number
sign x |
|
|

x > 0
x == 0
x < 0

=
=
=

1
0
-1

-- take the first n elements from a list
take
take
take

0
_
n

_
[]
(x:xs)

=
=
=

[]
[]
x : take (n-1) xs

-- generate some javascript
valueToJs
valueToJs
valueToJs
valueToJs
...

:: Options -> ModuleName -> Environment -> Value -> JS
_ _ _ (NumericLiteral n) = JSNumericLiteral n
_ _ _ (StringLiteral s) = JSStringLiteral s
_ _ _ (BooleanLiteral b) = JSBooleanLiteral b
Intro - Examples
sealed trait Level
case object Level1 extends Level
case object Level2 extends Level

sealed trait Title
case object DBAdmin extends Title
case class SWEngineer(level: Level) extends Title

case class Employee(manager: Option[Employee], name: String, title: Title)

val employees = ???

val selfManagedLevel2Engineers = employees.collect {
case Employee(None, name, SWEngineer(Level2)) => name
}
Pattern Matching 101
Filter
Does it have the structure I
want? [Yes/No]
If so, extract out the pieces
that are relevant to me.

Extract
Pattern Matching 101
-- take the first n elements from a list
take 0
_
= []
take _
[]
= []
take n
(x:xs)
= x : take (n-1) xs

Filter - does it have non-empty list structure?

Extract - Give me ‘head’ and ‘tail’
Pattern Matching 101
Products

Sums

case class Employee(

sealed trait Title

manager: Option[Employee],
name:

String,

title:

case object DBAdmin extends Title

terms

Title

case class SWEngineer(level: Level)
extends Title

)
class Account {

interface Shape { }

...

class Rect extends Shape { … }

public Account(BigDecimal balance, User holder) {

class Ellipse extends Shape { … }

...
}
}

class Pentagon extends Shape { … }

terms
First-Class-ness 101
data Maybe a = Nothing | Just a deriving (Eq, Ord)

class Person {
public Person(String name, int age) {
...
}
}
First-Class-ness 101

Magic interferes with your ability to
abstract and compose.
Magical Patterns
Ordinary Duplication
sealed
object
…
case
case

trait Provenance
Provenance {
class Either(left: Provenance, right: Provenance) extends Provenance
class Both(left: Provenance, right: Provenance) extends Provenance

def allOf(xs: Seq[Provenance]): Provenance = {
if (xs.length == 0) Unknown
else if (xs.length == 1) xs.head
else xs.reduce(Both.apply)
}
def anyOf(xs: Seq[Provenance]): Provenance = {
if (xs.length == 0) Unknown
else if (xs.length == 1) xs.head
else xs.reduce(Either.apply)
}
}
Magical Patterns
Factoring
sealed
object
case
case
case
case
case

trait Provenance
Provenance {
object Unknown extends Provenance
object Value extends Provenance
class Relation(value: SqlRelation) extends Provenance
class Either(left: Provenance, right: Provenance) extends Provenance
class Both(left: Provenance, right: Provenance) extends Provenance

def allOf(xs: Seq[Provenance]): Provenance = reduce(xs)(Both.apply)
def anyOf(xs: Seq[Provenance]): Provenance = reduce(xs)(Either.apply)
private def reduce(xs: Seq[Provenance])(
f: (Provenance, Provenance) => Provenance): Provenance = {
if (xs.length == 0) Unknown
else if (xs.length == 1) xs.head
else xs.reduce(f)
}
}
Magical Patterns
Factoringz
sealed
object
case
case
case
case
case

trait Provenance
Provenance {
object Unknown extends Provenance
object Value extends Provenance
class Relation(value: SqlRelation) extends Provenance
class Either(left: Provenance, right: Provenance) extends Provenance
class Both(left: Provenance, right: Provenance) extends Provenance

private def strict[A, B, C](f: (A, B) => C): (A, => B) => C = (a, b) => f(a, b)
val BothMonoid
= Monoid.instance(strict[Provenance, Provenance, Provenance](Both.apply), Unknown)
val EitherMonoid = Monoid.instance(strict[Provenance, Provenance, Provenance](Either.apply), Unknown)
def allOf(xs: List[Provenance]): Provenance = Foldable[List].foldMap(xs)(identity)(BothMonoid)
def anyOf(xs: List[Provenance]): Provenance = Foldable[List].foldMap(xs)(identity)(EitherMonoid)
}
Magical Patterns
Toxic Duplication - Abstraction Fail
val Add = Mapping(
"(+)", "Adds two numeric values" NumericDomain,
,
(partialTyper {
case Type.Const(Data.Number(v1)) :: v2 :: Nil if (v1.signum == 0) => v2
case v1 :: Type.Const(Data.Number(v2)) :: Nil if (v2.signum == 0) => v1
case Type.Const(Data.
Int(v1)) :: Type.Const(Data.
Int(v2)) :: Nil =>
Type.Const(Data.
Int(v1 + v2))
case Type.Const(Data.Number(v1)) :: Type.Const(Data.Number(v2)) ::
Nil =>
Type.Const(Data.Dec(v1 + v2))
}) ||| numericWidening
)
Magical Patterns
Pattern Combinators - Composition Fail
● Product & sum
○ PartialFunction.orElse

● Negation
● Defaults
● Use-case specific
Magical Patterns
Magical patterns limit your ability
to abstract over patterns and to
compose them together to create new
patterns.
First-Class Patterns
First-class patterns are built using
other language features so you can
abstract and compose them.
First-Class Patterns
Haskell Example
ex4 :: Either (Int,Int) Int -> Int
ex4 a = match a $
(1+) <$> (left (pair var (cst 4)) ->> id
<|>

right var

->> id)

<|> left (pair __ var) ->> id

http://hackage.haskell.org/package/first-class-patterns
First-Class Patterns
“For the rest of us”
X match {
case Y => Z
}

type Pattern???
First-Class Patterns
Structure
Input

X match {
Output

case Y => Z
}

type Pattern???

Extraction
First-Class Patterns
One ‘Option’
Input

X match {
Output

case Y => Z
}

Extraction

type Pattern[X, Z] = X => Option[Z]
First-Class Patterns
Basic Patterns
def some[A, B](p: Pattern[A, B]): Pattern[Option[A], B] = _.flatMap(p)
def none[A, B]: Pattern[A, B] = Function.const( None)
def k[A](v0: A): Pattern[A, A] = v => if (v == v0) Some(v0) else None
def or[A, B](p1: Pattern[A, B], p2: Pattern[A, B]): Pattern[A, B] =
v => p1(v).orElse(p2(v))
scala> or(none, some(k( 2)))(Some(2))
res3: Option[Int] = Some(2)
https://gist.github.com/jdegoes/9240971
First-Class Patterns - JS
And Now in JavaScript….Because

http://jsfiddle.net/AvL4V/
First-Class Patterns
Limitations
● Extractors cannot throw away information,
leading to ‘dummy parameters’
● Negation not possible under any
circumstances
● No partiality warnings or built-in catch all
Exercises
1. Define a Pattern Combinator to Fix:
val Add = Mapping(
"(+)", "Adds two numeric values" NumericDomain,
,
(partialTyper {
case Type.Const(Data.Number(v1)) :: v2 :: Nil if (v1.signum == 0) => v2
case v1 :: Type.Const(Data.Number(v2)) :: Nil if (v2.signum == 0) => v1
case Type.Const(Data.
Int(v1)) :: Type.Const(Data.
Int(v2)) :: Nil =>
Type.Const(Data.
Int(v1 + v2))
case Type.Const(Data.Number(v1)) :: Type.Const(Data.Number(v2)) ::
Nil =>
Type.Const(Data.Dec(v1 + v2))
}) ||| numericWidening
)

EASY
Exercises
2. Define ‘Pattern’ and some core
patterns in the language of your choice

EASY
Exercises
3. Define an ‘And’ pattern that requires
both inputs match

EASY
Exercises
4. Define an alternate definition of
pattern (along with a few core patterns)
that permits pattern negation
4.b Optional: Use this to allow catch-alls
MODERATE
Exercises
5. Define an alternate definition of
pattern (along with a few core patterns)
that permits extractors to throw away
information

HARD
THANK YOU
First-Class Patterns
John A. De Goes - @jdegoes
Frontier Developers, February 26

More Related Content

What's hot (20)

PDF
The Death of Final Tagless
John De Goes
 
PDF
Halogen: Past, Present, and Future
John De Goes
 
PDF
The Design of the Scalaz 8 Effect System
John De Goes
 
PDF
Scala jargon cheatsheet
Ruslan Shevchenko
 
PDF
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
John De Goes
 
PDF
One Monad to Rule Them All
John De Goes
 
PDF
Humble introduction to category theory in haskell
Jongsoo Lee
 
PPTX
Scala Back to Basics: Type Classes
Tomer Gabel
 
PPTX
Joy of scala
Maxim Novak
 
PDF
Introduction to functional programming using Ocaml
pramode_ce
 
PDF
Monad Transformers In The Wild
StackMob Inc
 
PDF
Pragmatic Real-World Scala (short version)
Jonas Bonér
 
PDF
Demystifying functional programming with Scala
Denis
 
PDF
Orthogonal Functional Architecture
John De Goes
 
PDF
"Немного о функциональном программирование в JavaScript" Алексей Коваленко
Fwdays
 
PDF
Refactoring Functional Type Classes
John De Goes
 
PDF
Few simple-type-tricks in scala
Ruslan Shevchenko
 
PDF
GUL UC3M - Introduction to functional programming
David Muñoz Díaz
 
PDF
T3chFest 2016 - The polyglot programmer
David Muñoz Díaz
 
PDF
O caml2014 leroy-slides
OCaml
 
The Death of Final Tagless
John De Goes
 
Halogen: Past, Present, and Future
John De Goes
 
The Design of the Scalaz 8 Effect System
John De Goes
 
Scala jargon cheatsheet
Ruslan Shevchenko
 
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
John De Goes
 
One Monad to Rule Them All
John De Goes
 
Humble introduction to category theory in haskell
Jongsoo Lee
 
Scala Back to Basics: Type Classes
Tomer Gabel
 
Joy of scala
Maxim Novak
 
Introduction to functional programming using Ocaml
pramode_ce
 
Monad Transformers In The Wild
StackMob Inc
 
Pragmatic Real-World Scala (short version)
Jonas Bonér
 
Demystifying functional programming with Scala
Denis
 
Orthogonal Functional Architecture
John De Goes
 
"Немного о функциональном программирование в JavaScript" Алексей Коваленко
Fwdays
 
Refactoring Functional Type Classes
John De Goes
 
Few simple-type-tricks in scala
Ruslan Shevchenko
 
GUL UC3M - Introduction to functional programming
David Muñoz Díaz
 
T3chFest 2016 - The polyglot programmer
David Muñoz Díaz
 
O caml2014 leroy-slides
OCaml
 

Similar to First-Class Patterns (20)

PDF
(How) can we benefit from adopting scala?
Tomasz Wrobel
 
PDF
Scala for Jedi
Vladimir Parfinenko
 
PDF
A bit about Scala
Vladimir Parfinenko
 
PPTX
Scala
suraj_atreya
 
PDF
The Scala Programming Language
league
 
PDF
From Java to Scala - advantages and possible risks
SeniorDevOnly
 
PDF
Introduction to-scala
Hamid Jafarian
 
PDF
ML-CheatSheet (1).pdf
KarroumAbdelmalek
 
PDF
Monadologie
league
 
PPT
SDC - Einführung in Scala
Christian Baranowski
 
ODP
Introducing scala
Meetu Maltiar
 
PDF
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
PDF
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
PDF
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
PDF
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
PDF
Scala Bootcamp 1
Knoldus Inc.
 
PPT
Scala introduction
Yardena Meymann
 
PDF
Introduction to scala
Michel Perez
 
PDF
Introduction to Scala
Aleksandar Prokopec
 
PDF
Introduction to Python
UC San Diego
 
(How) can we benefit from adopting scala?
Tomasz Wrobel
 
Scala for Jedi
Vladimir Parfinenko
 
A bit about Scala
Vladimir Parfinenko
 
The Scala Programming Language
league
 
From Java to Scala - advantages and possible risks
SeniorDevOnly
 
Introduction to-scala
Hamid Jafarian
 
ML-CheatSheet (1).pdf
KarroumAbdelmalek
 
Monadologie
league
 
SDC - Einführung in Scala
Christian Baranowski
 
Introducing scala
Meetu Maltiar
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
Scala Bootcamp 1
Knoldus Inc.
 
Scala introduction
Yardena Meymann
 
Introduction to scala
Michel Perez
 
Introduction to Scala
Aleksandar Prokopec
 
Introduction to Python
UC San Diego
 
Ad

More from John De Goes (16)

PDF
Error Management: Future vs ZIO
John De Goes
 
PDF
Atomically { Delete Your Actors }
John De Goes
 
PDF
Scalaz Stream: Rebirth
John De Goes
 
PDF
Scalaz Stream: Rebirth
John De Goes
 
PDF
ZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional Programming
John De Goes
 
PDF
ZIO Queue
John De Goes
 
PDF
Scalaz 8 vs Akka Actors
John De Goes
 
PDF
Streams for (Co)Free!
John De Goes
 
PDF
Getting Started with PureScript
John De Goes
 
PPTX
SlamData - How MongoDB Is Powering a Revolution in Visual Analytics
John De Goes
 
PPTX
The Dark Side of NoSQL
John De Goes
 
PDF
Quirrel & R for Dummies
John De Goes
 
PDF
In-Database Predictive Analytics
John De Goes
 
PDF
Analytics Maturity Model
John De Goes
 
PDF
Rise of the scientific database
John De Goes
 
PDF
Fun with automata
John De Goes
 
Error Management: Future vs ZIO
John De Goes
 
Atomically { Delete Your Actors }
John De Goes
 
Scalaz Stream: Rebirth
John De Goes
 
Scalaz Stream: Rebirth
John De Goes
 
ZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional Programming
John De Goes
 
ZIO Queue
John De Goes
 
Scalaz 8 vs Akka Actors
John De Goes
 
Streams for (Co)Free!
John De Goes
 
Getting Started with PureScript
John De Goes
 
SlamData - How MongoDB Is Powering a Revolution in Visual Analytics
John De Goes
 
The Dark Side of NoSQL
John De Goes
 
Quirrel & R for Dummies
John De Goes
 
In-Database Predictive Analytics
John De Goes
 
Analytics Maturity Model
John De Goes
 
Rise of the scientific database
John De Goes
 
Fun with automata
John De Goes
 
Ad

Recently uploaded (20)

PDF
MASTERDECK GRAPHSUMMIT SYDNEY (Public).pdf
Neo4j
 
PPTX
Introduction to Flutter by Ayush Desai.pptx
ayushdesai204
 
PPTX
Agile Chennai 18-19 July 2025 | Emerging patterns in Agentic AI by Bharani Su...
AgileNetwork
 
PDF
The Future of Artificial Intelligence (AI)
Mukul
 
PPTX
What-is-the-World-Wide-Web -- Introduction
tonifi9488
 
PDF
Build with AI and GDG Cloud Bydgoszcz- ADK .pdf
jaroslawgajewski1
 
PPTX
Applied-Statistics-Mastering-Data-Driven-Decisions.pptx
parmaryashparmaryash
 
PDF
A Strategic Analysis of the MVNO Wave in Emerging Markets.pdf
IPLOOK Networks
 
PPTX
Simple and concise overview about Quantum computing..pptx
mughal641
 
PPTX
AI in Daily Life: How Artificial Intelligence Helps Us Every Day
vanshrpatil7
 
PPTX
IT Runs Better with ThousandEyes AI-driven Assurance
ThousandEyes
 
PDF
Data_Analytics_vs_Data_Science_vs_BI_by_CA_Suvidha_Chaplot.pdf
CA Suvidha Chaplot
 
PPTX
OA presentation.pptx OA presentation.pptx
pateldhruv002338
 
PDF
AI Unleashed - Shaping the Future -Starting Today - AIOUG Yatra 2025 - For Co...
Sandesh Rao
 
PDF
Researching The Best Chat SDK Providers in 2025
Ray Fields
 
PPTX
AI Code Generation Risks (Ramkumar Dilli, CIO, Myridius)
Priyanka Aash
 
PDF
Brief History of Internet - Early Days of Internet
sutharharshit158
 
PDF
Research-Fundamentals-and-Topic-Development.pdf
ayesha butalia
 
PPTX
The Future of AI & Machine Learning.pptx
pritsen4700
 
PDF
Tea4chat - another LLM Project by Kerem Atam
a0m0rajab1
 
MASTERDECK GRAPHSUMMIT SYDNEY (Public).pdf
Neo4j
 
Introduction to Flutter by Ayush Desai.pptx
ayushdesai204
 
Agile Chennai 18-19 July 2025 | Emerging patterns in Agentic AI by Bharani Su...
AgileNetwork
 
The Future of Artificial Intelligence (AI)
Mukul
 
What-is-the-World-Wide-Web -- Introduction
tonifi9488
 
Build with AI and GDG Cloud Bydgoszcz- ADK .pdf
jaroslawgajewski1
 
Applied-Statistics-Mastering-Data-Driven-Decisions.pptx
parmaryashparmaryash
 
A Strategic Analysis of the MVNO Wave in Emerging Markets.pdf
IPLOOK Networks
 
Simple and concise overview about Quantum computing..pptx
mughal641
 
AI in Daily Life: How Artificial Intelligence Helps Us Every Day
vanshrpatil7
 
IT Runs Better with ThousandEyes AI-driven Assurance
ThousandEyes
 
Data_Analytics_vs_Data_Science_vs_BI_by_CA_Suvidha_Chaplot.pdf
CA Suvidha Chaplot
 
OA presentation.pptx OA presentation.pptx
pateldhruv002338
 
AI Unleashed - Shaping the Future -Starting Today - AIOUG Yatra 2025 - For Co...
Sandesh Rao
 
Researching The Best Chat SDK Providers in 2025
Ray Fields
 
AI Code Generation Risks (Ramkumar Dilli, CIO, Myridius)
Priyanka Aash
 
Brief History of Internet - Early Days of Internet
sutharharshit158
 
Research-Fundamentals-and-Topic-Development.pdf
ayesha butalia
 
The Future of AI & Machine Learning.pptx
pritsen4700
 
Tea4chat - another LLM Project by Kerem Atam
a0m0rajab1
 

First-Class Patterns

  • 1. First-Class Patterns John A. De Goes - @jdegoes Frontier Developers, February 26
  • 2. Agenda ● ● ● ● ● ● Intro Pattern Matching 101 First-Class-ness 101 Magical Patterns First-Class Patterns Exercises
  • 3. Intro Pattern Matching ● Divides a (possibly infinite) set of values into a discrete number of cases, where each case can be handled in a uniform way ● “if” on steroids ○ Sometimes strictly more powerful (e.g. Haskell)
  • 4. Intro - Examples -- sign of a number sign x | | | x > 0 x == 0 x < 0 = = = 1 0 -1 -- take the first n elements from a list take take take 0 _ n _ [] (x:xs) = = = [] [] x : take (n-1) xs -- generate some javascript valueToJs valueToJs valueToJs valueToJs ... :: Options -> ModuleName -> Environment -> Value -> JS _ _ _ (NumericLiteral n) = JSNumericLiteral n _ _ _ (StringLiteral s) = JSStringLiteral s _ _ _ (BooleanLiteral b) = JSBooleanLiteral b
  • 5. Intro - Examples sealed trait Level case object Level1 extends Level case object Level2 extends Level sealed trait Title case object DBAdmin extends Title case class SWEngineer(level: Level) extends Title case class Employee(manager: Option[Employee], name: String, title: Title) val employees = ??? val selfManagedLevel2Engineers = employees.collect { case Employee(None, name, SWEngineer(Level2)) => name }
  • 6. Pattern Matching 101 Filter Does it have the structure I want? [Yes/No] If so, extract out the pieces that are relevant to me. Extract
  • 7. Pattern Matching 101 -- take the first n elements from a list take 0 _ = [] take _ [] = [] take n (x:xs) = x : take (n-1) xs Filter - does it have non-empty list structure? Extract - Give me ‘head’ and ‘tail’
  • 8. Pattern Matching 101 Products Sums case class Employee( sealed trait Title manager: Option[Employee], name: String, title: case object DBAdmin extends Title terms Title case class SWEngineer(level: Level) extends Title ) class Account { interface Shape { } ... class Rect extends Shape { … } public Account(BigDecimal balance, User holder) { class Ellipse extends Shape { … } ... } } class Pentagon extends Shape { … } terms
  • 9. First-Class-ness 101 data Maybe a = Nothing | Just a deriving (Eq, Ord) class Person { public Person(String name, int age) { ... } }
  • 10. First-Class-ness 101 Magic interferes with your ability to abstract and compose.
  • 11. Magical Patterns Ordinary Duplication sealed object … case case trait Provenance Provenance { class Either(left: Provenance, right: Provenance) extends Provenance class Both(left: Provenance, right: Provenance) extends Provenance def allOf(xs: Seq[Provenance]): Provenance = { if (xs.length == 0) Unknown else if (xs.length == 1) xs.head else xs.reduce(Both.apply) } def anyOf(xs: Seq[Provenance]): Provenance = { if (xs.length == 0) Unknown else if (xs.length == 1) xs.head else xs.reduce(Either.apply) } }
  • 12. Magical Patterns Factoring sealed object case case case case case trait Provenance Provenance { object Unknown extends Provenance object Value extends Provenance class Relation(value: SqlRelation) extends Provenance class Either(left: Provenance, right: Provenance) extends Provenance class Both(left: Provenance, right: Provenance) extends Provenance def allOf(xs: Seq[Provenance]): Provenance = reduce(xs)(Both.apply) def anyOf(xs: Seq[Provenance]): Provenance = reduce(xs)(Either.apply) private def reduce(xs: Seq[Provenance])( f: (Provenance, Provenance) => Provenance): Provenance = { if (xs.length == 0) Unknown else if (xs.length == 1) xs.head else xs.reduce(f) } }
  • 13. Magical Patterns Factoringz sealed object case case case case case trait Provenance Provenance { object Unknown extends Provenance object Value extends Provenance class Relation(value: SqlRelation) extends Provenance class Either(left: Provenance, right: Provenance) extends Provenance class Both(left: Provenance, right: Provenance) extends Provenance private def strict[A, B, C](f: (A, B) => C): (A, => B) => C = (a, b) => f(a, b) val BothMonoid = Monoid.instance(strict[Provenance, Provenance, Provenance](Both.apply), Unknown) val EitherMonoid = Monoid.instance(strict[Provenance, Provenance, Provenance](Either.apply), Unknown) def allOf(xs: List[Provenance]): Provenance = Foldable[List].foldMap(xs)(identity)(BothMonoid) def anyOf(xs: List[Provenance]): Provenance = Foldable[List].foldMap(xs)(identity)(EitherMonoid) }
  • 14. Magical Patterns Toxic Duplication - Abstraction Fail val Add = Mapping( "(+)", "Adds two numeric values" NumericDomain, , (partialTyper { case Type.Const(Data.Number(v1)) :: v2 :: Nil if (v1.signum == 0) => v2 case v1 :: Type.Const(Data.Number(v2)) :: Nil if (v2.signum == 0) => v1 case Type.Const(Data. Int(v1)) :: Type.Const(Data. Int(v2)) :: Nil => Type.Const(Data. Int(v1 + v2)) case Type.Const(Data.Number(v1)) :: Type.Const(Data.Number(v2)) :: Nil => Type.Const(Data.Dec(v1 + v2)) }) ||| numericWidening )
  • 15. Magical Patterns Pattern Combinators - Composition Fail ● Product & sum ○ PartialFunction.orElse ● Negation ● Defaults ● Use-case specific
  • 16. Magical Patterns Magical patterns limit your ability to abstract over patterns and to compose them together to create new patterns.
  • 17. First-Class Patterns First-class patterns are built using other language features so you can abstract and compose them.
  • 18. First-Class Patterns Haskell Example ex4 :: Either (Int,Int) Int -> Int ex4 a = match a $ (1+) <$> (left (pair var (cst 4)) ->> id <|> right var ->> id) <|> left (pair __ var) ->> id http://hackage.haskell.org/package/first-class-patterns
  • 19. First-Class Patterns “For the rest of us” X match { case Y => Z } type Pattern???
  • 20. First-Class Patterns Structure Input X match { Output case Y => Z } type Pattern??? Extraction
  • 21. First-Class Patterns One ‘Option’ Input X match { Output case Y => Z } Extraction type Pattern[X, Z] = X => Option[Z]
  • 22. First-Class Patterns Basic Patterns def some[A, B](p: Pattern[A, B]): Pattern[Option[A], B] = _.flatMap(p) def none[A, B]: Pattern[A, B] = Function.const( None) def k[A](v0: A): Pattern[A, A] = v => if (v == v0) Some(v0) else None def or[A, B](p1: Pattern[A, B], p2: Pattern[A, B]): Pattern[A, B] = v => p1(v).orElse(p2(v)) scala> or(none, some(k( 2)))(Some(2)) res3: Option[Int] = Some(2) https://gist.github.com/jdegoes/9240971
  • 23. First-Class Patterns - JS And Now in JavaScript….Because http://jsfiddle.net/AvL4V/
  • 24. First-Class Patterns Limitations ● Extractors cannot throw away information, leading to ‘dummy parameters’ ● Negation not possible under any circumstances ● No partiality warnings or built-in catch all
  • 25. Exercises 1. Define a Pattern Combinator to Fix: val Add = Mapping( "(+)", "Adds two numeric values" NumericDomain, , (partialTyper { case Type.Const(Data.Number(v1)) :: v2 :: Nil if (v1.signum == 0) => v2 case v1 :: Type.Const(Data.Number(v2)) :: Nil if (v2.signum == 0) => v1 case Type.Const(Data. Int(v1)) :: Type.Const(Data. Int(v2)) :: Nil => Type.Const(Data. Int(v1 + v2)) case Type.Const(Data.Number(v1)) :: Type.Const(Data.Number(v2)) :: Nil => Type.Const(Data.Dec(v1 + v2)) }) ||| numericWidening ) EASY
  • 26. Exercises 2. Define ‘Pattern’ and some core patterns in the language of your choice EASY
  • 27. Exercises 3. Define an ‘And’ pattern that requires both inputs match EASY
  • 28. Exercises 4. Define an alternate definition of pattern (along with a few core patterns) that permits pattern negation 4.b Optional: Use this to allow catch-alls MODERATE
  • 29. Exercises 5. Define an alternate definition of pattern (along with a few core patterns) that permits extractors to throw away information HARD
  • 30. THANK YOU First-Class Patterns John A. De Goes - @jdegoes Frontier Developers, February 26