Skip to content

Instantly share code, notes, and snippets.

@Kaiepi
Last active August 8, 2019 04:37
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Kaiepi/f1888cd8c53b400a16870290a983338e to your computer and use it in GitHub Desktop.
Save Kaiepi/f1888cd8c53b400a16870290a983338e to your computer and use it in GitHub Desktop.
Monads in Perl 6
use v6.d;
role Monad[::T] {
method ACCEPTS(::?ROLE: ::?ROLE $m --> Bool:D) {
for $m.^attributes -> Attribute $x {
my Attribute $y = self.^get_attribute_for_usage: $x.name;
return False unless $x.get_value($m) ~~ $y.get_value(self);
}
True
}
method new (::?ROLE: | --> ::?ROLE) { ... } # AKA pure
method bind(::?ROLE: Callable[::?ROLE] --> ::?ROLE) { ... }
method then(::?ROLE: ::?ROLE --> ::?ROLE) { ... }
}
role Identity[::T] does Monad[T] {
has T $!value;
submethod BUILD(T :$!value) {}
method new(Identity: T $a --> Identity:D) {
self.bless: value => $a
}
method bind(Identity:D: Identity:D &f --> Identity:D) {
&f($!value)
}
method then(Identity:D: Identity:D $m --> Identity:D) {
$m
}
}
proto sub infix>>=»(|) {*}
multi sub infix>>=»(Monad:D $m, Monad:D &f --> Monad:D) {
$m.bind: &f
}
proto sub infix>>»(|) {*}
multi sub infix>>»(Monad:D $m, Mu $a --> Monad:D) {
$m.then: $a
}
proto sub pure(|) {*}
multi sub pure(Mu $a --> Identity:D) {
Identity[$a.WHAT].new: $a
}
sub f(Str $a --> Identity[Str]) { pure $a }
sub h(Str $a --> Identity[Str]) { pure ($a xx 2).join(' ') }
sub k(Str $a --> Identity[Str]) { pure $a.split(' ').head }
my Str $a = 'ayy lmao';
my Identity[Str] $m = pure $a;
say ($m >>= &h) ~~ &h($a); # OUTPUT: True
say ($m >>= &f) ~~ $m; # OUTPUT: True
say ($m >>= sub (Str $x --> Identity[Str]) {
&h($x) >>= &k
}) ~~ (($m >>= &h) >>= &k); # OUTPUT: True
@JJ
Copy link

JJ commented Aug 3, 2019

Cool. Probably need some time to fully understand it, but cool anyway.

@cognominal
Copy link

I wonder if pure functional programming in Perl 6 would deserve its own slang. Should it be Haskell like ?

@Kaiepi
Copy link
Author

Kaiepi commented Aug 6, 2019

I'm making this into a proper library that aims to make it possible to write monads in the same way you can in Haskell. It will use a slang for custom monad (and eventually monad-transformer) package declarators, generic references to monads from within package declarators using ::?MONAD/$?MONAD, as well as syntax for using <- in do blocks (if possible). I'll make a repo for it once I have the really rough parts of the metaprogramming required done.

@JJ
Copy link

JJ commented Aug 6, 2019 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment