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 |
That would be pretty awesome. Thanks!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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 eventuallymonad-transformer
) package declarators, generic references to monads from within package declarators using::?MONAD
/$?MONAD
, as well as syntax for using<-
indo
blocks (if possible). I'll make a repo for it once I have the really rough parts of the metaprogramming required done.