#!/usr/bin/perl package Monad; use Data::Dumper; use base 'Exporter'; our @EXPORT = qw/Identity Monad Fail Bind Return L /; use overload '>>' => 'Bind', q("") => sub { Dumper(shift) } ; sub L (&) { shift } # instead of "sub", looks a bit prettier sub Identity { my ($value) = @_; return bless \$value, 'Monad'; } sub Monad { my $monad = caller(1); } sub Lift { my $monad = caller(1); $monad->lift(@_); } sub Fail { my $monad = caller(1); $monad->fail(@_); } sub Bind { my $monad = shift; $monad->bind(@_); } sub Return { my $monad = caller(1); $monad->return(@_); } sub return { my ($class, $data) = @_; bless $data, $class; } sub lift { my ($class, $f) = @_; return sub { $class->return( $f->(@_) ); }; } sub bind { my ($self, $f) = @_; return $f->($self->mjoin); # default Identity monad } sub mjoin { my $self = shift; return $$self; } sub fail { my ($class, $exception) = @_; die $exception; } 1;