Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Functional Design Explained (David Sankel CppCon 2015)

624 views

Published on

An oft-cited benefit of learning a functional language is that it changes one's approach to solving problems for the better. The functional approach has such a strict emphasis on simplistic and highly composable solutions that an otherwise varied landscape of solution possibilities narrows down to only a few novel options.

This talk introduces functional design and showcases its application to several real-world problems. It will briefly cover denotational semantics and several math-based programming abstractions. Finally, the talk will conclude with a comparison of functional solutions to the results more traditional design methodologies.

No prior knowledge of functional programming or functional programming languages is required for this talk. All the examples make use of the C++ programming language.

Published in: Software
  • Be the first to comment

  • Be the first to like this

Functional Design Explained (David Sankel CppCon 2015)

  1. 1. 1 Functional Design Explained David Sankel - Stellar Science david@stellarscience.com CppCon 2015
  2. 2. 2 Math Engineering
  3. 3. 3Stellar ScienceDavid Sankel Quiz Are the following two C++ programs the same?
  4. 4. 4Stellar ScienceDavid Sankel Quiz Are the following two C++ programs the same? #include <iostream> int main( int argc, char** argv ) { std::cout << “Hello Worldn”; } #include <iostream> int main( int argc, char** argv ) { std:: cout << “Hello Worldn”; }
  5. 5. 5Stellar ScienceDavid Sankel Quiz Are the following two programs the same? #include <iostream> int main( int argc, char** argv ) { std::cout << “Hello Worldn”; } #!/usr/bin/env python print(“Hello World”)
  6. 6. 6Stellar ScienceDavid Sankel Quiz Are the following two programs the same? int f( int c ) { if( false ) return 45; else return c + 5; } int f( int c ) { int j = 5; j += c; return j; }
  7. 7. 7Stellar ScienceDavid Sankel 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?
  8. 8. 8Stellar ScienceDavid Sankel How about math? 3 + 2 = 5 5 = 3 + 2
  9. 9. 9Stellar ScienceDavid Sankel 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
  10. 10. 10Stellar ScienceDavid Sankel What is the meaning of this? int f( int c ) { if( false ) return 45; else return c + 5; }
  11. 11. 11Stellar ScienceDavid Sankel Function Meaning We could represent a function as a set of pairs As in: { …,(-1,4), (0,5), (1,6),…} Or as a lambda equation: λc. c + 5 Or something else: f(c) = c + 5 int f( int c ) { if( false ) return 45; else return c + 5; }
  12. 12. 12Stellar ScienceDavid Sankel Function Meaning What about this? int f( int c ) { for(;;) ; return 45; } …,(-1, ⊥),(0,⊥),(1, ⊥),… ⊥ is “bottom”
  13. 13. 13Stellar ScienceDavid Sankel 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)
  14. 14. 14Stellar ScienceDavid Sankel Why not drop the C++ nonsense and go Haskell? Haskell variant with optimizations: 0.41s C++ variant without optimizations: 0.16s 0 0.2 0.4 0.6 Haskell C++ Quicksort 160,000 ints
  15. 15. 15Stellar ScienceDavid Sankel Languages and Machines
  16. 16. 16Stellar ScienceDavid Sankel 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’.
  17. 17. 17Stellar ScienceDavid Sankel 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.
  18. 18. 18Stellar ScienceDavid Sankel 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.
  19. 19. 19Stellar ScienceDavid Sankel Algebraic Data Types • Mathematical fundamentals of base types. • Two types, 1 and 0 • Two ops, ⊕ and ⊗, to compose them
  20. 20. 20Stellar ScienceDavid Sankel 0 Type 0 is the type with no values struct Zero { Zero() = delete; };
  21. 21. 21Stellar ScienceDavid Sankel 1 Type 1 is the type with one value struct One {};
  22. 22. 22Stellar ScienceDavid Sankel 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; };
  23. 23. 23Stellar ScienceDavid Sankel Product Is this an implementation of a ⊗ b? struct AAndB { std::unique_ptr<A> a; std::unique_ptr<B> b; };
  24. 24. 24Stellar ScienceDavid Sankel 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
  25. 25. 25Stellar ScienceDavid Sankel 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)>;
  26. 26. 26Stellar ScienceDavid Sankel 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
  27. 27. 27Stellar ScienceDavid Sankel 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
  28. 28. 28Stellar ScienceDavid Sankel What is a movie?
  29. 29. 29Stellar ScienceDavid Sankel 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
  30. 30. 30Stellar ScienceDavid Sankel Grey flux movie auto greyFluxMovie = transform( []( double timeInSeconds ) -> Image { double dummy; double greyness = std::modf( timeInSeconds, &dummy ); return greyImage( greyness ); , time );
  31. 31. 31Stellar ScienceDavid Sankel What is a stream?
  32. 32. 32Stellar ScienceDavid Sankel 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> ) >;
  33. 33. 33Stellar ScienceDavid Sankel 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 ); };
  34. 34. 34Stellar ScienceDavid Sankel 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 ); }
  35. 35. 35Stellar ScienceDavid Sankel 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 ) >;
  36. 36. 36Stellar ScienceDavid Sankel 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 );
  37. 37. 37Stellar ScienceDavid Sankel 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;
  38. 38. 38Stellar ScienceDavid Sankel What is command line processing?
  39. 39. 39Stellar ScienceDavid Sankel What is command line processing? μ⟦ CommandLineProcessor<a> ⟧ = ListOf String → μ⟦ a ⟧ ? Hrm… μ⟦ Parser<a,b> ⟧ = ListOf μ⟦ a ⟧ → μ⟦ b ⟧ μ⟦ CommandLineProcessor<a> ⟧ = μ⟦ Parser<String,b> ⟧
  40. 40. 40Stellar ScienceDavid Sankel 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}; })
  41. 41. 41Stellar ScienceDavid Sankel 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};}));
  42. 42. 42Stellar ScienceDavid Sankel Benefits • Highly Flexible • Highly Composible • Type safe • Simple
  43. 43. 43Stellar ScienceDavid Sankel Functional Design 1. Discover the essence 2. Derive the implementation • Beautiful API’s • Screaming Speed david@stellarscience.com

×