#!/usr/bin/perl package Blondie::ADTs; use strict; use warnings; { package Blondie::Unit; sub new { my $class = shift; my $value = shift; bless \$value, $class; } sub val { ${ $_[0] } } sub str { "${ $_[0] }" } sub fmap { my $self = shift; my $f = shift; my $res = (ref $self)->new($f->($self->val)); } } { package Blondie::List; sub new { my $class = shift; bless [@_], $class; } sub str { map { "$_" } @{ $_[0] } } sub fmap { my $self = shift; my $f = shift; (ref $self)->new(map { &$f($_) } @$self); } sub values { @{ $_[0] } } } { package Blondie::Map; sub new { my $class = shift; bless {@_}, $class; } sub AUTOLOAD { our $AUTOLOAD =~ /([^:]+)$/; my $method = $1; my $a = sub { $_[0]{$method} }; { no strict 'refs'; *{$method} = $a; } $_[0]->$a; } sub can { my $self = shift; my $key = shift; exists $self->{$key} || $self->SUPER::can($key); } sub get { $_[0]{$_[1]} } sub fmap { my $self = shift; my $f = shift; (ref $self)->new( map { $_ => &$f($self->get($_)) } $self->keys ); } sub values { values %{ $_[0] } } sub keys { keys %{ $_[0] } } sub str { map { "$_ => $_[0]{$_}" } $_[0]->keys; } sub merge { my $self = shift; my $other = shift; (ref $self)->new(%$self, %$other); } } { package Blondie::Env; use base qw/Blondie::Map/; } __PACKAGE__; __END__ =pod =head1 NAME Blondie::ADTs - Reused abstract data types. =head1 SYNOPSIS use Blondie::ADTs; # Blondie::Map, Blondie::Unit and Blondie::List are defined =head1 DESCRIPTION These ADTs are the implementation classes of all the L and some more objects. They provide stringification, fmapping and value encapsulation features. They are discussed in the main L documentation. =cut