Functional Design Explained - David Sankel - CppCon 2015

Download as pdf or txt
Download as pdf or txt
You are on page 1of 43

Functional

Design
Explained
David Sankel - Stellar Science
[email protected]
CppCon 2015

1
Math Engineering

2
Quiz
Are the following two C++ programs the same?

David Sankel Stellar Science 3


Quiz
Are the following two C++ programs the same?

#include <iostream> #include <iostream>

int main( int argc, char** argv ) int main( int argc, char** argv )
{ {
std::cout << “Hello World\n”; std:: cout << “Hello World\n”;
} }

David Sankel Stellar Science 4


Quiz
Are the following two programs the same?

#include <iostream> #!/usr/bin/env python

int main( int argc, char** argv ) print(“Hello World”)


{
std::cout << “Hello World\n”;
}

David Sankel Stellar Science 5


Quiz
Are the following two programs the same?

int f( int c ) int f( int c )


{ {
if( false ) int j = 5;
return 45; j += c;
else return j;
return c + 5; }
}

David Sankel Stellar Science 6


Essence of Programs
Ideally we would like:
• Strong equivalence properties
• Something written down
• A set of rules we can apply to any program

Any ideas of what would be a good essence language?

David Sankel Stellar Science 7


How about math?

3+2=5

5=3+2

David Sankel Stellar Science 8


Denotational Semantics
Developed by Dana Scott and Christopher Strachey in late 1960s

Write a mathematical function to convert syntax to meaning (in


math).

μ⟦e₁ + e₂⟧ = μ⟦e₁ ⟧ + μ⟦e₂⟧ where eᵢ is an expression


μ⟦i⟧ = i where i is an integer

David Sankel Stellar Science 9


What is the meaning of this?

int f( int c )
{
if( false )
return 45;
else
return c + 5;
}

David Sankel Stellar Science 10


Function Meaning
We could represent a int f( int c )
{
function as a set of pairs
if( false )
As in: return 45;
else
return c + 5;
{ …,(-1,4), (0,5), (1,6),…}
}

Or as a lambda equation: λc. c + 5

Or something else: f(c) = c + 5

David Sankel Stellar Science 11


Function Meaning
What about this?
int f( int c )
{
for(;;) ;
return 45;
}

…,(-1, ⊥),(0,⊥),(1, ⊥),…

⊥ is “bottom”

David Sankel Stellar Science 12


The Next 700 Programming
Languages
P. J. Landin wrote in 1966 about his programming language
ISWIM (If you See What I Mean)

f(b+2c) + f(2b-c)
where f(x) = x(x+a)

David Sankel Stellar Science 13


Why not drop the C++
nonsense and go Haskell?
Quicksort 160,000 ints

0.6

0.4

0.2

0
Haskell C++

Haskell variant with optimizations: 0.41s


C++ variant without optimizations: 0.16s
David Sankel Stellar Science 14
Languages and Machines

David Sankel Stellar Science 15


Semantics Discovery
• Discover the mathematical essence of
a problem and derive an
implementation.
• Conal Elliott, various applications of
semantics discovery throughout career.
• See ‘Denotational design with type
class morphisms’.

David Sankel Stellar Science 16


Ingredients
• Math augmented with some extra constructs can represent
the essence of code.
• Write programs in math.
• C++ straddles more levels of abstraction than any other
language.
• Discover essence of problem using math and derive
implementation.

David Sankel Stellar Science 17


Functional Design
1. Discover the mathematical essence of the problem and write
it out.
2. Derive an efficient implementation in C++ that has the
interface discovered in #1.

David Sankel Stellar Science 18


Algebraic Data Types
• Mathematical fundamentals of base types.
• Two types, 1 and 0
• Two ops, ⊕ and ⊗, to compose them

David Sankel Stellar Science 19


0 Type
0 is the type with no values

struct Zero {
Zero() = delete;
};

David Sankel Stellar Science 20


1 Type
1 is the type with one value

struct One {};

David Sankel Stellar Science 21


Product
Given types ‘a’ and ‘b’, the product of ‘a’ and ‘b’ (a ⊗ b) is a type
whose values have an ‘a’ and a ‘b’.

using AAndB = std::pair<A,B>;

using AAndB = std::tuple<A,B>;

struct AAndB {
A a;
B b;
};

David Sankel Stellar Science 22


Product
Is this an implementation of a ⊗ b?

struct AAndB {
std::unique_ptr<A> a;
std::unique_ptr<B> b;
};

David Sankel Stellar Science 23


Sum
A ⊕ B is a type whose values are either a value of type ‘A’ or a value of type
‘B’.

struct AOrB {
bool hasA;
union {
A a;
B b;
} contents; // ‘a’ when ‘hasA==true’
// otherwise ‘b’.
};

using AOrB = boost::variant< A, B >;

using AOrB = std::variant< A, B >; // hopefully

David Sankel Stellar Science 24


Function Type
A → B is a type whose values are pure functions with an input
type A and an return type B.

using FunctionAB = std::function<B (A)>;

David Sankel Stellar Science 25


Meaning
μ⟦ syntax ⟧ = mathExpression
The meaning of “syntax” is the math expression

μ⟦ expression ⟧ : mathExpression
The type of “expression” is the math expression

μ⟦ int ⟧ = ℤ
μ⟦ 3 ⟧ : ℤ
μ⟦ 3 ⟧ = 3

David Sankel Stellar Science 26


Some Examples
μ⟦ boost::optional<e₁> ⟧ = μ⟦ e₁ ⟧ ⊕ 1

μ⟦ std::pair<e₁,e₂> ⟧ = μ⟦ e₁ ⟧ ⊗ μ⟦ e₂ ⟧

μ⟦ double ⟧ = ℝ

or maybe

μ⟦ double ⟧ = ℝ ⊕ 1⊕ 1⊕ 1
where the extra states are -∞, +∞, and NaN

David Sankel Stellar Science 27


What is a movie?

David Sankel Stellar Science 28


What is a movie?
μ⟦ Movie<e> ⟧ = ℝ → μ⟦ e ⟧

Operations:
μ⟦ always<e> ⟧ : μ⟦ e ⟧ → μ⟦ Movie<e> ⟧
μ⟦ always<e>(a) ⟧ = λ t. μ⟦ a ⟧

μ⟦ snapshot<e> ⟧ : μ⟦Movie<e>⟧ → ℝ → A
μ⟦ snapshot<e>(movie, time) ⟧ = μ⟦ movie ⟧ ( μ⟦ time ⟧ )

μ⟦ transform<A,B> ⟧ : (μ⟦A⟧ → μ⟦B⟧) → μ⟦Movie<A>⟧ → μ⟦Movie<B>⟧

μ⟦ timeMovie ⟧ : μ⟦ Movie<double> ⟧
μ⟦ timeMovie ⟧ = λ t. t

David Sankel Stellar Science 29


Grey flux movie
auto greyFluxMovie = transform(
[]( double timeInSeconds ) -> Image {
double dummy;
double greyness = std::modf( timeInSeconds, &dummy );
return greyImage( greyness );
, time );

David Sankel Stellar Science 30


What is a stream?

David Sankel Stellar Science 31


What is a stream?
Let ‘Action’ be some side-effecting operation.

μ⟦ sink<e> ⟧ = μ⟦ e ⟧ → Action
μ⟦ source<e> ⟧ = (μ⟦ e ⟧ → Action) → Action

template< typename T >


using sink = std::function<void ( const T & )>;

template< typename T >


using source = std::function<void ( sink<T> ) >;

David Sankel Stellar Science 32


Example source/sink
source<char> consoleInput = []( sink<char> s ) {
int inputChar;
while( (inputChar = std::cin.get()) != EOF ) {
s( static_cast< char >( inputChar ) );
};

sink<char> consoleOutput = []( char c ) {


std::cout.put( c );
};

David Sankel Stellar Science 33


Connecting Sources and Sinks
μ⟦ connect<e> ⟧ : μ⟦ source<e> ⟧ → μ⟦ sink<e> ⟧ → Action
μ⟦ connect<e>( so, si ) ⟧ = μ⟦ so ⟧( μ⟦ si ⟧ )

template< typename t >


void connect( source<t> so, sink<t> si ) {
so( si );
}

int main( int argc, char** argv ) {


connect( consoleInput, consoleOutput );
}

David Sankel Stellar Science 34


Transforming Streams
μ⟦ sink<e> ⟧ = μ⟦ e ⟧ → Action

μ⟦ transform<a,b> ⟧ = μ⟦ Sink<b> ⟧ → μ⟦ Sink<a> ⟧


= μ⟦ Sink<b> ⟧ → (μ⟦ a ⟧ → Action)
= μ⟦ Sink<b> ⟧ → μ⟦ a ⟧ → Action

template< typename a, typename b >


using transform = std::function<void ( sink<b>, a ) >;

David Sankel Stellar Science 35


Application of Transforms
μ⟦ transform<a,b> ⟧ = μ⟦ sink<b> ⟧ → μ⟦ a ⟧ → Action

μ⟦ applyToSink<a,b> ⟧
: μ⟦ transform<a,b> ⟧ → μ⟦ sink<b> ⟧ → μ⟦ sink<a> ⟧

μ⟦ applyToSource<a,b> ⟧
: μ⟦ transform<a,b> ⟧ → μ⟦ source<a> ⟧ → μ⟦ source<b> ⟧

μ⟦ so >> t ⟧ = μ⟦ applyToSource<a,b> ⟧( t, so );
μ⟦ t >> si ⟧ = μ⟦ applyToSink<a,b> ⟧( t, si );
μ⟦ so >> si ⟧ = μ⟦ connect<t> ⟧( so, si );

David Sankel Stellar Science 36


Tranformers Continued…
transformer<char, std::string> getLines = //…
transformer<std::string, char> unWords = //…

source<string> inputLines = consoleInput >> getLines;


sink<string> wordOutput = unwords >> consoleOutput;
InputLines >> wordOutput;

transformer<char,char> linesToSpaces = getLines >> unwords;

David Sankel Stellar Science 37


What is command line
processing?

David Sankel Stellar Science 38


What is command line
processing?
μ⟦ CommandLineProcessor<a> ⟧ = ListOf String → μ⟦ a ⟧ ?

Hrm…

μ⟦ Parser<a,b> ⟧ = ListOf μ⟦ a ⟧ → μ⟦ b ⟧

μ⟦ CommandLineProcessor<a> ⟧ = μ⟦ Parser<String,b> ⟧

David Sankel Stellar Science 39


Command Line Parsing
struct HelpFlag{};
struct UserFlag{
std::string user;
};

auto flagP = mix(


args(“--help”, HelpFlag()),
args(“--user“ >> stringP,
[]( std::string username ) { return UserFlag{username}; })

David Sankel Stellar Science 40


Command Line Parsing
struct ListAccounts {};
struct ListJob {
int jobId;
};

struct CommandLineParse {
std::vector< boost::variant< HelpFlag, UserFlag > > globalFlags;
boost::variant< ListAccounts, ListJob > mode;
};

auto parser = flagP


>> (args( “listAccounts”, ListAccounts() ) ||
(args( “listJob” ) >> “--jobId” >> intP( []( int id ) { return ListJob{id};}));

David Sankel Stellar Science 41


Benefits
• Highly Flexible
• Highly Composible
• Type safe
• Simple

David Sankel Stellar Science 42


Functional
Design

1. Discover the essence


2. Derive the
implementation

• Beautiful API’s
• Screaming Speed

David Sankel [email protected] Stellar Science 43

You might also like