Functional pe(a)rls London Perl Workshop 29/11/2008 version 2 osfameron
A sequence Debolaz, on #moose a list of numbers like 10,  25,  50, 100, 250, 500, 1000,  etc   without tracking any other state than the number itself
A sequence 1.  (power of 10)     * 2.5  2.  * 2 3.  * 2
A sequence without tracking any other state than the number itself
A sequence /^1/
A sequence /^1/   # power of 10
A sequence cycle [2.5, 2, 2]
A sequence cycle [2.5, 2, 2] 2.5 2 2 2.5 ...
A sequence Oops!  Perl doesn't have infinite sequences
A sequence Iterators
A sequence curry cycle (@list) { my @curr = @list; return sub { @curr = @list  unless @curr; return shift @curr; }; }
A sequence my $c = cycle    [2.5, 2, 2];
A sequence my $c = cycle    [2.5, 2, 2]; say $c->();  # 2.5 say $c->();  # 2 say $c->();  # 2 say $c->();  # 2.5 ...
A sequence cycle [2.5, 2, 2];
A sequence 10, cycle [2.5, 2, 2];
A sequence   mult,  10, cycle [2.5, 2, 2];
(curry)‏ curry mult ($x,$y) {  $x * $y  }
(curry)‏ say mult( 3, 4 ); # 12
(curry)‏ my $triple = mult(3); say $triple->(10); # 30
(curry)‏ my $multiply = mult; say $multiply->(6, 8);
(curry)‏ my $multiply = \&mult; my $multiply = mult;
A sequence   mult ,  10, cycle [2.5, 2, 2];
A sequence scan    mult,  10, cycle [2.5, 2, 2];
(Scanning)‏ scan  add,  1, [2, 3, 4]; # [1, 3, 6, 10]
A sequence scan    mult,  10, cycle  [2.5, 2, 2];
A sequence take 12 =>  scan    mult,  10, cycle [2.5, 2, 2];
A sequence say for  take 12 =>  scan    mult,  10, cycle [2.5, 2, 2];
A sequence 10 25 50 100 250 500 ...
How? Iterators (HOP)‏ HOP::Stream Lazy variables
How? Iterators (HOP)‏ FP (scan, take)‏
How? Iterators (HOP)‏ FP (scan, take)‏ Sub::Curried
How? Iterators (HOP)‏ FP (scan, take)‏ Sub::Curried Devel::Declare
Devel::Declare curry mult ($x,$y) {  $x * $y  }
Devel::Declare New syntax! (But better than source filters)‏
Devel::Declare New syntax! (But better than source filters)‏ Method declaration MooseX::Declare Sub::Auto
Devel::Declare New syntax! (But better than source filters)‏ Currying Monads Pattern Matching List comprehensions Functions that work on @arrays and lists
Devel::Declare In Perl! (With a bit of scary XS magic)‏ hooks into the compiler changing the source as you compile horrible perl tricks to get methods installed, and braces closed mst++, rafl++
Some light relief
Some light relief Monads
Monads Come from maths “ Category theory”
Monads Come from maths “ Category theory” Very clever people rave about them being useful
Monads Come from maths “ Category theory” Very clever people rave about them being useful Have a reputation for being hard to understand
Monad tutorials
Monad tutorials
Monad tutorials
Monad tutorials
Monad tutorials Step 1: Write Monad Tutorial
Monad tutorials Step 2: ???
Monad tutorials Step 3: Profit!
Monads You already use monads
Monads You already use monads YAY!
Monads You already use monads Sequences of commands?
Sequencing my $x = 1; my $y = 2; my $z = $x * $y; say “$x * $y = $z”;
Sequencing my $x = 1; my $y = 2; my $z = $x * $y; say “$x * $y = $z”;
Sequencing my $x = 1; my $y = 2; my $z = $x * $y; say “$x * $y = $z”;
Sequencing my @seq = sub { my $x = 1 }, sub { my $y = 2 }, sub { my $z = $x * $y }, sub { say "$x * $y = $z"  };
Sequencing my @seq = sub { my $x = 1 }, sub { my $y = 2 }, sub { my $z = $x * $y }, sub { say "$x * $y = $z"  }; # Global symbol "$x" requires explicit package name at  ...
Nesting my $x = 1; my $y = 2; my $z = $x * $y; say “$x * $y = $z”;
Nesting sub { my $x = 1; sub { my $y = 2; sub { my $z = $x * $y; sub { say "$x * $y = $z"; }->() }->() }->() }->();
Monads made pretty Source filters! http://sleepingsquirrel.org/monads/monads.html
Monads made pretty Source filters! http://sleepingsquirrel.org/monads/monads.html Source tree manipulation (B::OP magic)‏ Deparse and source text munging
Monads made pretty We want a syntax like mdo {   my $x = mbind(1);   my $y = mbind(2);   my $z = mbind($x + $y);   say “$x * $y = $z”; }
Monads made pretty We want a syntax like mdo {   my $x = mbind(1);   my $y = mbind(2);   my $z = mbind($x + $y);   say “$x * $y = $z”; } mdo  introduces the block mbind  gives us a hook to rotate around
Optree munging 19:  my $x << Just 2; ... n  <;> nextstate(main 2078 b.pl:19) v:*,&,$ ->o t  <2> left_shift[t3] vK ->u o  <0> padsv[$x:2078,2080] sM/LVINTRO ->p s  <1> entersub[t2] sKS/TARG,3 ->t -  <1> ex-list sK ->s p  <0> pushmark s ->q q  <$> const(IV 2) sM ->r -  <1> ex-rv2cv sK/130 ->- r  <$> gv(*Just) s ->s u  <;> nextstate(main 2079 b.pl:20) v:*,&,$ ->v #  :  mbind (Just 2), sub { my $x = shift; ... };   <;> nextstate(main  b.pl:) v:*,&,{,$ ->   <@> list K ->   <0> pushmark s ->   <1> entersub[t2] KS/TARG,3 -> -  <1> ex-list K ->   <0> pushmark s ->   <1> entersub[t1] lKMS/NO(),TARG,INARGS,3 -> -  <1> ex-list lK ->   <0> pushmark s ->   <$> const(IV 2) sM -> -  <1> ex-rv2cv sK/130 ->-   <$> gv(*Just) s -> -  <1> ex-rv2cv sK/2 ->-   # mbind instead of >>   <$> gv(*mbind) s ->   <1> refgen K/1 -> -  <1> ex-list lKRM ->   <0> pushmark sRM ->   <$> anoncode[CV ] lRM ->   #  ??? set up anon sub   # my $x = shift   <0> padsv[$x:2078,2080] sM/LVINTRO ->p   # the next ; is moved into this new lambda!   <;> nextstate(main 2079 b.pl:20) v:*,&,$ ->v
Optree munging 19:  my $x << Just 2; ... n  <;> nextstate(main 2078 b.pl:19) v:*,&,$ ->o t  <2> left_shift[t3] vK ->u o  <0> padsv[$x:2078,2080] sM/LVINTRO ->p s  <1> entersub[t2] sKS/TARG,3 ->t -  <1> ex-list sK ->s p  <0> pushmark s ->q q  <$> const(IV 2) sM ->r -  <1> ex-rv2cv sK/130 ->- r  <$> gv(*Just) s ->s u  <;> nextstate(main 2079 b.pl:20) v:*,&,$ ->v #  :  mbind (Just 2), sub { my $x = shift; ... };   <;> nextstate(main  b.pl:) v:*,&,{,$ ->   <@> list K ->   <0> pushmark s ->   <1> entersub[t2] KS/TARG,3 -> -  <1> ex-list K ->   <0> pushmark s ->   <1> entersub[t1] lKMS/NO(),TARG,INARGS,3 -> -  <1> ex-list lK ->   <0> pushmark s ->   <$> const(IV 2) sM -> -  <1> ex-rv2cv sK/130 ->-   <$> gv(*Just) s -> -  <1> ex-rv2cv sK/2 ->-   # mbind instead of >>   <$> gv(*mbind) s ->   <1> refgen K/1 -> -  <1> ex-list lKRM ->   <0> pushmark sRM ->   <$> anoncode[CV ] lRM ->   #  ??? set up anon sub   # my $x = shift   <0> padsv[$x:2078,2080] sM/LVINTRO ->p   # the next ; is moved into this new lambda!   <;> nextstate(main 2079 b.pl:20) v:*,&,$ ->v KABOOM
Source deparsing Works surprisingly well
Source deparsing Works surprisingly well for trivial cases (a bit fragile)‏
Source deparsing Works surprisingly well for trivial cases (a bit fragile)‏ though localised to mdo { ... }
Devel::Declare Even nicer syntax mdo {   mbind $x = 1;   mbind $y = 2;   mbind $z = $x + $y;   say “$x * $y = $z”; }
Devel::Declare And cuter implementation: mdo {   mbind $x = 1;   mbind $y = 2;   mbind $z = $x + $y;   say “$x * $y = $z”; }
Devel::Declare The problem: mdo {   mbind 1, sub { my $x = shift;   mbind 2, sub { my $y = shift;   mbind $x + $y,   sub { my $z = shift;   say “$x * $y = $z”;   }   ...
Devel::Declare No need to count nesting: scope_inject Scope::Guard Use to inject a ; at the end of method declarations: method foo ($x) {   print $x; }  # look Ma, no semicolon!
Devel::Declare mbind's scope_inject adds a “}” mdo {   mbind 1, sub { my $x = shift;   mbind 2, sub { my $y = shift;   mbind  $x + $y,   sub  {  my $z = shift;   say “$x * $y = $z”;   }  # adds a closing brace   }
Devel::Declare mbind's scope_inject adds a “}” mdo {   mbind 1, sub { my $x = shift;   mbind  2, sub  {  my $y = shift;   mbind $x + $y,   sub { my $z = shift;   say “$x * $y = $z”;   }   }  # adds a closing brace   }
Devel::Declare mbind's scope_inject adds a “}” mdo {   mbind  1, sub  {  my $x = shift;   mbind 2, sub { my $y = shift;   mbind $x + $y,   sub { my $z = shift;   say “$x * $y = $z”;   }   }   }  # adds a closing brace   }
Devel::Declare mbind's scope_inject adds a “}” mdo   {   mbind 1, sub { my $x = shift;   mbind 2, sub { my $y = shift;   mbind $x + $y,   sub { my $z = shift;   say “$x * $y = $z”;   }   }   }   }   # closes block
So... We can now sequence commands! mdo {   mbind $x = 1;   mbind $y = 2;   mbind $z = $x + $y;   say “$x * $y = $z”; }
So... We can now sequence commands! YAY?
So... We can now sequence commands! OK, so this was big news in Haskell in 1990s
So... We can now sequence commands! OK, so this was big news in Haskell in 1990s Imperative languages have always done this
What else can monads  do  ? Sequencing mdo {   mbind $x = 1;   mbind $y = 2;   mbind $z = $x + $y;   say “$x * $y = $z”; }
What else can monads  do  ? Sequencing mdo {   mbind  $x = 1;   mbind  $y = 2;   mbind  $z = $x + $y;   say “$x * $y = $z”; }
What else can monads  do  ? Sequencing mdo {   mbind $x = 1 ;   mbind $y = 2 ;   mbind $z = $x + $y ;   say “$x * $y = $z”; }
What else can monads  do  ? Sequencing mdo {   mbind $x = 1 ;   mbind $y = 2 ;   mbind $z = $x + $y ;   say “$x * $y = $z”; } Programmable semicolon!
Maybe Success/Failure mdo (Maybe) {   mbind $FH = m_open('<', $file) ;   mbind $line = <$FH> ;   mbind $val  = lookup(\%h, $line) ;   say “Found $val!”; }
Maybe Success/Failure mdo (Maybe) {   mbind $FH = m_open('<', $file) ;   mbind $line = <$FH> ;   mbind $val  = lookup(\%h, $line) ;   say “Found $val!”; } Will give up if can't open file, read a line from it, or look it up in a hash
Maybe Success/Failure mdo (Maybe) {   mbind $FH = m_open('<', $file) ;   mbind $line = <$FH> ;   mbind $val  = lookup(\%h, $line) ;   say “Found $val!”; } Compare chain of if (foo) { if (bar) { ... or eval { ... }
Maybe $FH = open($file)‏ $line = <$FH> $val = lookup ( $line )‏ say “Found $val”
Maybe $FH = open($file)‏ $line = <$FH> $val = lookup ( $line )‏ say “Found $val”
Sequence
Maybe ? ? ?
Multiple (List)‏
List $x = [1..10] $y = [1..10] guard $x+$y == 10 say “$x+$y=10”
List Cartesian product mdo {   mbind $x = [1..10] ;   mbind $y = [1..10] ;   mbind guard $x+$y == 10 ;   say “$x+$y=10”; } Run every $x against every $y and filter
List Cartesian product mdo {   mbind $x = [1..10] ;   mbind $y = [1..10] ;   mbind guard $x+$y == 10 ;   say “$x+$y=10”; } 1+9=10 2+8=10 ...
List Cartesian product mdo {   mbind $x = [1..10] ;   mbind $y = [1..10] ;   mbind guard $x+$y == 10 ;   say “$x+$y=10”; } just like SQL or LINQ
List comprehension More compact syntax mcomp ($x <- [1..10];    $y <- [1..10];   $x+y==10)    { say “$x+$y=10” }
List mdo {   mbind  $x =  [1..10] ;   mbind  $y =  [1..10] ;   mbind  guard $x+$y == 10;   say “$x+$y=10”; } We're actually calling mbind on a list
List mdo {   mbind  $x =  [1..10] ;   mbind  $y =  [1..10] ;   mbind  guard $x+$y == 10;   say “$x+$y=10”; } We're actually calling mbind on a list autobox
Perl++ Not really a functional language... But you can take it surprisingly far (CPAN++)‏
What else can I do with monads? Parsing Error handling SQL generation Continuations (real resumable ones)‏
Wants monads now! Techniques are valuable now Nicely wrapped implementation will be ready soon....
Thanks! questions?

Functional Pe(a)rls version 2

  • 1.
    Functional pe(a)rls LondonPerl Workshop 29/11/2008 version 2 osfameron
  • 2.
    A sequence Debolaz,on #moose a list of numbers like 10, 25, 50, 100, 250, 500, 1000, etc without tracking any other state than the number itself
  • 3.
    A sequence 1. (power of 10) * 2.5 2. * 2 3. * 2
  • 4.
    A sequence withouttracking any other state than the number itself
  • 5.
  • 6.
    A sequence /^1/ # power of 10
  • 7.
    A sequence cycle[2.5, 2, 2]
  • 8.
    A sequence cycle[2.5, 2, 2] 2.5 2 2 2.5 ...
  • 9.
    A sequence Oops! Perl doesn't have infinite sequences
  • 10.
  • 11.
    A sequence currycycle (@list) { my @curr = @list; return sub { @curr = @list unless @curr; return shift @curr; }; }
  • 12.
    A sequence my$c = cycle [2.5, 2, 2];
  • 13.
    A sequence my$c = cycle [2.5, 2, 2]; say $c->(); # 2.5 say $c->(); # 2 say $c->(); # 2 say $c->(); # 2.5 ...
  • 14.
    A sequence cycle[2.5, 2, 2];
  • 15.
    A sequence 10,cycle [2.5, 2, 2];
  • 16.
    A sequence mult, 10, cycle [2.5, 2, 2];
  • 17.
    (curry)‏ curry mult($x,$y) { $x * $y }
  • 18.
  • 19.
    (curry)‏ my $triple= mult(3); say $triple->(10); # 30
  • 20.
    (curry)‏ my $multiply= mult; say $multiply->(6, 8);
  • 21.
    (curry)‏ my $multiply= \&mult; my $multiply = mult;
  • 22.
    A sequence mult , 10, cycle [2.5, 2, 2];
  • 23.
    A sequence scan mult, 10, cycle [2.5, 2, 2];
  • 24.
    (Scanning)‏ scan add, 1, [2, 3, 4]; # [1, 3, 6, 10]
  • 25.
    A sequence scan mult, 10, cycle [2.5, 2, 2];
  • 26.
    A sequence take12 => scan mult, 10, cycle [2.5, 2, 2];
  • 27.
    A sequence sayfor take 12 => scan mult, 10, cycle [2.5, 2, 2];
  • 28.
    A sequence 1025 50 100 250 500 ...
  • 29.
    How? Iterators (HOP)‏HOP::Stream Lazy variables
  • 30.
    How? Iterators (HOP)‏FP (scan, take)‏
  • 31.
    How? Iterators (HOP)‏FP (scan, take)‏ Sub::Curried
  • 32.
    How? Iterators (HOP)‏FP (scan, take)‏ Sub::Curried Devel::Declare
  • 33.
    Devel::Declare curry mult($x,$y) { $x * $y }
  • 34.
    Devel::Declare New syntax!(But better than source filters)‏
  • 35.
    Devel::Declare New syntax!(But better than source filters)‏ Method declaration MooseX::Declare Sub::Auto
  • 36.
    Devel::Declare New syntax!(But better than source filters)‏ Currying Monads Pattern Matching List comprehensions Functions that work on @arrays and lists
  • 37.
    Devel::Declare In Perl!(With a bit of scary XS magic)‏ hooks into the compiler changing the source as you compile horrible perl tricks to get methods installed, and braces closed mst++, rafl++
  • 38.
  • 39.
  • 40.
    Monads Come frommaths “ Category theory”
  • 41.
    Monads Come frommaths “ Category theory” Very clever people rave about them being useful
  • 42.
    Monads Come frommaths “ Category theory” Very clever people rave about them being useful Have a reputation for being hard to understand
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
    Monad tutorials Step1: Write Monad Tutorial
  • 48.
  • 49.
  • 50.
  • 51.
    Monads You alreadyuse monads YAY!
  • 52.
    Monads You alreadyuse monads Sequences of commands?
  • 53.
    Sequencing my $x= 1; my $y = 2; my $z = $x * $y; say “$x * $y = $z”;
  • 54.
    Sequencing my $x= 1; my $y = 2; my $z = $x * $y; say “$x * $y = $z”;
  • 55.
    Sequencing my $x= 1; my $y = 2; my $z = $x * $y; say “$x * $y = $z”;
  • 56.
    Sequencing my @seq= sub { my $x = 1 }, sub { my $y = 2 }, sub { my $z = $x * $y }, sub { say &quot;$x * $y = $z&quot; };
  • 57.
    Sequencing my @seq= sub { my $x = 1 }, sub { my $y = 2 }, sub { my $z = $x * $y }, sub { say &quot;$x * $y = $z&quot; }; # Global symbol &quot;$x&quot; requires explicit package name at ...
  • 58.
    Nesting my $x= 1; my $y = 2; my $z = $x * $y; say “$x * $y = $z”;
  • 59.
    Nesting sub {my $x = 1; sub { my $y = 2; sub { my $z = $x * $y; sub { say &quot;$x * $y = $z&quot;; }->() }->() }->() }->();
  • 60.
    Monads made prettySource filters! http://sleepingsquirrel.org/monads/monads.html
  • 61.
    Monads made prettySource filters! http://sleepingsquirrel.org/monads/monads.html Source tree manipulation (B::OP magic)‏ Deparse and source text munging
  • 62.
    Monads made prettyWe want a syntax like mdo { my $x = mbind(1); my $y = mbind(2); my $z = mbind($x + $y); say “$x * $y = $z”; }
  • 63.
    Monads made prettyWe want a syntax like mdo { my $x = mbind(1); my $y = mbind(2); my $z = mbind($x + $y); say “$x * $y = $z”; } mdo introduces the block mbind gives us a hook to rotate around
  • 64.
    Optree munging 19: my $x << Just 2; ... n <;> nextstate(main 2078 b.pl:19) v:*,&,$ ->o t <2> left_shift[t3] vK ->u o <0> padsv[$x:2078,2080] sM/LVINTRO ->p s <1> entersub[t2] sKS/TARG,3 ->t - <1> ex-list sK ->s p <0> pushmark s ->q q <$> const(IV 2) sM ->r - <1> ex-rv2cv sK/130 ->- r <$> gv(*Just) s ->s u <;> nextstate(main 2079 b.pl:20) v:*,&,$ ->v # : mbind (Just 2), sub { my $x = shift; ... }; <;> nextstate(main b.pl:) v:*,&,{,$ -> <@> list K -> <0> pushmark s -> <1> entersub[t2] KS/TARG,3 -> - <1> ex-list K -> <0> pushmark s -> <1> entersub[t1] lKMS/NO(),TARG,INARGS,3 -> - <1> ex-list lK -> <0> pushmark s -> <$> const(IV 2) sM -> - <1> ex-rv2cv sK/130 ->- <$> gv(*Just) s -> - <1> ex-rv2cv sK/2 ->- # mbind instead of >> <$> gv(*mbind) s -> <1> refgen K/1 -> - <1> ex-list lKRM -> <0> pushmark sRM -> <$> anoncode[CV ] lRM -> # ??? set up anon sub # my $x = shift <0> padsv[$x:2078,2080] sM/LVINTRO ->p # the next ; is moved into this new lambda! <;> nextstate(main 2079 b.pl:20) v:*,&,$ ->v
  • 65.
    Optree munging 19: my $x << Just 2; ... n <;> nextstate(main 2078 b.pl:19) v:*,&,$ ->o t <2> left_shift[t3] vK ->u o <0> padsv[$x:2078,2080] sM/LVINTRO ->p s <1> entersub[t2] sKS/TARG,3 ->t - <1> ex-list sK ->s p <0> pushmark s ->q q <$> const(IV 2) sM ->r - <1> ex-rv2cv sK/130 ->- r <$> gv(*Just) s ->s u <;> nextstate(main 2079 b.pl:20) v:*,&,$ ->v # : mbind (Just 2), sub { my $x = shift; ... }; <;> nextstate(main b.pl:) v:*,&,{,$ -> <@> list K -> <0> pushmark s -> <1> entersub[t2] KS/TARG,3 -> - <1> ex-list K -> <0> pushmark s -> <1> entersub[t1] lKMS/NO(),TARG,INARGS,3 -> - <1> ex-list lK -> <0> pushmark s -> <$> const(IV 2) sM -> - <1> ex-rv2cv sK/130 ->- <$> gv(*Just) s -> - <1> ex-rv2cv sK/2 ->- # mbind instead of >> <$> gv(*mbind) s -> <1> refgen K/1 -> - <1> ex-list lKRM -> <0> pushmark sRM -> <$> anoncode[CV ] lRM -> # ??? set up anon sub # my $x = shift <0> padsv[$x:2078,2080] sM/LVINTRO ->p # the next ; is moved into this new lambda! <;> nextstate(main 2079 b.pl:20) v:*,&,$ ->v KABOOM
  • 66.
    Source deparsing Workssurprisingly well
  • 67.
    Source deparsing Workssurprisingly well for trivial cases (a bit fragile)‏
  • 68.
    Source deparsing Workssurprisingly well for trivial cases (a bit fragile)‏ though localised to mdo { ... }
  • 69.
    Devel::Declare Even nicersyntax mdo { mbind $x = 1; mbind $y = 2; mbind $z = $x + $y; say “$x * $y = $z”; }
  • 70.
    Devel::Declare And cuterimplementation: mdo { mbind $x = 1; mbind $y = 2; mbind $z = $x + $y; say “$x * $y = $z”; }
  • 71.
    Devel::Declare The problem:mdo { mbind 1, sub { my $x = shift; mbind 2, sub { my $y = shift; mbind $x + $y, sub { my $z = shift; say “$x * $y = $z”; } ...
  • 72.
    Devel::Declare No needto count nesting: scope_inject Scope::Guard Use to inject a ; at the end of method declarations: method foo ($x) { print $x; } # look Ma, no semicolon!
  • 73.
    Devel::Declare mbind's scope_injectadds a “}” mdo { mbind 1, sub { my $x = shift; mbind 2, sub { my $y = shift; mbind $x + $y, sub { my $z = shift; say “$x * $y = $z”; } # adds a closing brace }
  • 74.
    Devel::Declare mbind's scope_injectadds a “}” mdo { mbind 1, sub { my $x = shift; mbind 2, sub { my $y = shift; mbind $x + $y, sub { my $z = shift; say “$x * $y = $z”; } } # adds a closing brace }
  • 75.
    Devel::Declare mbind's scope_injectadds a “}” mdo { mbind 1, sub { my $x = shift; mbind 2, sub { my $y = shift; mbind $x + $y, sub { my $z = shift; say “$x * $y = $z”; } } } # adds a closing brace }
  • 76.
    Devel::Declare mbind's scope_injectadds a “}” mdo { mbind 1, sub { my $x = shift; mbind 2, sub { my $y = shift; mbind $x + $y, sub { my $z = shift; say “$x * $y = $z”; } } } } # closes block
  • 77.
    So... We cannow sequence commands! mdo { mbind $x = 1; mbind $y = 2; mbind $z = $x + $y; say “$x * $y = $z”; }
  • 78.
    So... We cannow sequence commands! YAY?
  • 79.
    So... We cannow sequence commands! OK, so this was big news in Haskell in 1990s
  • 80.
    So... We cannow sequence commands! OK, so this was big news in Haskell in 1990s Imperative languages have always done this
  • 81.
    What else canmonads do ? Sequencing mdo { mbind $x = 1; mbind $y = 2; mbind $z = $x + $y; say “$x * $y = $z”; }
  • 82.
    What else canmonads do ? Sequencing mdo { mbind $x = 1; mbind $y = 2; mbind $z = $x + $y; say “$x * $y = $z”; }
  • 83.
    What else canmonads do ? Sequencing mdo { mbind $x = 1 ; mbind $y = 2 ; mbind $z = $x + $y ; say “$x * $y = $z”; }
  • 84.
    What else canmonads do ? Sequencing mdo { mbind $x = 1 ; mbind $y = 2 ; mbind $z = $x + $y ; say “$x * $y = $z”; } Programmable semicolon!
  • 85.
    Maybe Success/Failure mdo(Maybe) { mbind $FH = m_open('<', $file) ; mbind $line = <$FH> ; mbind $val = lookup(\%h, $line) ; say “Found $val!”; }
  • 86.
    Maybe Success/Failure mdo(Maybe) { mbind $FH = m_open('<', $file) ; mbind $line = <$FH> ; mbind $val = lookup(\%h, $line) ; say “Found $val!”; } Will give up if can't open file, read a line from it, or look it up in a hash
  • 87.
    Maybe Success/Failure mdo(Maybe) { mbind $FH = m_open('<', $file) ; mbind $line = <$FH> ; mbind $val = lookup(\%h, $line) ; say “Found $val!”; } Compare chain of if (foo) { if (bar) { ... or eval { ... }
  • 88.
    Maybe $FH =open($file)‏ $line = <$FH> $val = lookup ( $line )‏ say “Found $val”
  • 89.
    Maybe $FH =open($file)‏ $line = <$FH> $val = lookup ( $line )‏ say “Found $val”
  • 90.
  • 91.
  • 92.
  • 93.
    List $x =[1..10] $y = [1..10] guard $x+$y == 10 say “$x+$y=10”
  • 94.
    List Cartesian productmdo { mbind $x = [1..10] ; mbind $y = [1..10] ; mbind guard $x+$y == 10 ; say “$x+$y=10”; } Run every $x against every $y and filter
  • 95.
    List Cartesian productmdo { mbind $x = [1..10] ; mbind $y = [1..10] ; mbind guard $x+$y == 10 ; say “$x+$y=10”; } 1+9=10 2+8=10 ...
  • 96.
    List Cartesian productmdo { mbind $x = [1..10] ; mbind $y = [1..10] ; mbind guard $x+$y == 10 ; say “$x+$y=10”; } just like SQL or LINQ
  • 97.
    List comprehension Morecompact syntax mcomp ($x <- [1..10]; $y <- [1..10]; $x+y==10) { say “$x+$y=10” }
  • 98.
    List mdo { mbind $x = [1..10] ; mbind $y = [1..10] ; mbind guard $x+$y == 10; say “$x+$y=10”; } We're actually calling mbind on a list
  • 99.
    List mdo { mbind $x = [1..10] ; mbind $y = [1..10] ; mbind guard $x+$y == 10; say “$x+$y=10”; } We're actually calling mbind on a list autobox
  • 100.
    Perl++ Not reallya functional language... But you can take it surprisingly far (CPAN++)‏
  • 101.
    What else canI do with monads? Parsing Error handling SQL generation Continuations (real resumable ones)‏
  • 102.
    Wants monads now!Techniques are valuable now Nicely wrapped implementation will be ready soon....
  • 103.