Last active
August 8, 2019 04:37
-
-
Save Kaiepi/f1888cd8c53b400a16870290a983338e to your computer and use it in GitHub Desktop.
Monads in Perl 6
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
I wonder if pure functional programming in Perl 6 would deserve its own slang. Should it be Haskell like ?
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.
That would be pretty awesome. Thanks!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Cool. Probably need some time to fully understand it, but cool anyway.