Last active
September 26, 2016 03:21
-
-
Save alphaKAI/21c1254357d66ae8ac08e66b24077a96 to your computer and use it in GitHub Desktop.
Maybe Monad in D(I'm studying Haskell thus this code might have a lots of misunderstandings)
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
| import std.traits, | |
| std.conv; | |
| /* | |
| class Functor F where | |
| fmap :: (A -> B) -> FA -> FB | |
| */ | |
| interface Functor(F) { | |
| F fmap(AB = typeof((A _) => B.init), A, B)(AB, F); | |
| } | |
| /* | |
| class Functor f => Applicative (f :: * -> *) where | |
| pure :: a -> f a | |
| (<*>) :: f (a -> b) -> f a -> f b | |
| <*> is ap | |
| */ | |
| interface Applicative(F) : Functor!(Applicative!F) { | |
| ReturnType!F _pure(A)(A); | |
| F ap(AB = typeof((A _) => B.init), A, B)(AB, F); | |
| } | |
| enum MaybeState { | |
| Nothing, | |
| Just | |
| } | |
| /** | |
| instance Functor Maybe where | |
| fmap func (Just val) = Just (func val) | |
| fmap func Nothing = Nothing | |
| */ | |
| class Maybe : Functor!Maybe, Applicative!Maybe { | |
| MaybeState state; | |
| this (MaybeState state) { this.state = state; } | |
| // Is this code needed? | |
| auto fmap(F)(F func) { | |
| static if (this.state == MaybeState.Just) { | |
| return cast(Just!(Parameters!F[0]))(this).fmap(func); | |
| } else { | |
| return cast(Nothing)(this).fmap(func); | |
| } | |
| } | |
| static Just!T _pure(T)(T t) { | |
| return new Just!T(t); | |
| } | |
| } | |
| auto _pure(F, A)(A a) { | |
| return F._pure(a); | |
| } | |
| A _pure(A)(A a) { | |
| return a; | |
| } | |
| class Just(T) : Maybe, Applicative!(Just!T) { | |
| T val; | |
| this(T t) { | |
| val = t; | |
| super(MaybeState.Just); | |
| } | |
| Just!(ReturnType!F) fmap(F)(F func) { return new Just!(ReturnType!F)(func(this.val)); } | |
| override string toString() { return "(Just!" ~ T.stringof ~ " " ~ val.to!string ~ ")"; } | |
| // Applicative | |
| auto ap(J: Just!X, X)(J just) if (isCallable!T) { | |
| return new Just!(ReturnType!val)(val(just.val)); | |
| } | |
| } | |
| class Nothing : Maybe { | |
| this() { super(MaybeState.Nothing); } | |
| Nothing fmap(F)(F func) { return new Nothing; } | |
| override string toString() { return "Nothing"; } | |
| } | |
| class Func(F) : Functor!F { | |
| F f; | |
| this(F f) { this.f = f; } | |
| typeof ( | |
| (Parameters!R[0] x) => f(ReturnType!R.init) | |
| ) fmap(G: Func!R, R)(G g) { | |
| return (Parameters!R[0] x) => f(g.f(x)); | |
| } | |
| // Applicative | |
| Just!(ReturnType!F) fmap(J: Just!E, E)(J j) { | |
| return new Just!(ReturnType!F)(f(j.val)); | |
| } | |
| override string toString() { | |
| return Parameters!F[0].stringof ~ " -> " ~ ReturnType!F.stringof; | |
| } | |
| } | |
| auto func(F)(F func) if (isCallable!F) { | |
| return new Func!F(func); | |
| } | |
| // Utility Class(inspired from underscore.js) | |
| static class _ { | |
| static N delegate(N) plus(N)(N n) if (isNumeric!N) { | |
| return (N m) => m + n; | |
| } | |
| static N delegate(N) mul(N)(N n) if (isNumeric!N) { | |
| return (N m) => m * n; | |
| } | |
| } | |
| // Helper Functions | |
| auto just(T)(T t) { return new Just!T(t); } | |
| auto nothing() { return new Nothing; } | |
| /* | |
| import Data.Char | |
| import Control.Monad | |
| numUpper x y s = do | |
| guard $ length s == x + y | |
| euard $ length (filter isDigit $ take x s) == x | |
| guard $ length (filter isUpper $ drop x s) == y | |
| Just s | |
| */ | |
| Maybe numUpper(int x, int y, string s) { | |
| if (!(s.length == x + y)) { | |
| return nothing; | |
| } | |
| import std.algorithm, std.range, std.ascii; | |
| if (!((s.take(x).filter!(isDigit)).array.length == x)) { | |
| return nothing; | |
| } | |
| if (!((s.drop(x).filter!(isUpper)).array.length == y)) { | |
| return nothing; | |
| } | |
| return just(s); | |
| } | |
| class List(T) : Functor!(List!T) { | |
| T[] list; | |
| this(T[] list) { this.list = list; } | |
| import std.algorithm, std.array, std.range; | |
| auto fmap(F)(F func) if (isCallable!F && arity!func == 1) { | |
| return new List!(ReturnType!F)(list.map!(x => func(x)).array); | |
| } | |
| auto ap(L: List!X, X)(L _list) if (isCallable!T && is(X == Parameters!T[0])) { | |
| return new List!(ReturnType!T)(this.fmap(((T fun) => _list.fmap(fun))).list.map!(x => x.list).join); | |
| } | |
| override string toString() { | |
| static if (isCallable!T) { | |
| return "[" ~ list.map!(x => T.stringof).join(", ") ~ "]"; | |
| } else { | |
| return "[" ~ list.map!(x => x.to!string).join(", ") ~ "]"; | |
| } | |
| } | |
| } | |
| auto list(T...)() { | |
| alias E = typeof(T[0]); | |
| E[] _list; | |
| foreach (e; T) { | |
| _list ~= e; | |
| } | |
| return new List!E(_list); | |
| } | |
| // demo | |
| import std.stdio; | |
| void main() { | |
| // The equivalent Haskell code is : fmap (+3) (Just 2) | |
| just(2).fmap(_.plus(3)).writeln; | |
| // ditto : fmap (+3) Nothing | |
| nothing.fmap(_.plus(3)).writeln; | |
| // ditto : :type (+3) | |
| func(_.plus(3)).writeln; | |
| // ditto : fmap (+3) (+2) $ 10 | |
| func(_.plus(3)).fmap(func(_.plus(2)))(10).writeln; | |
| /* | |
| print $ numUpper 3 2 "123AB" | |
| print $ numUpper 3 2 "123ABC" | |
| print $ numUpper 3 2 "12ABC" | |
| */ | |
| writeln(numUpper(3, 2, "123AB")); | |
| writeln(numUpper(3, 2, "123ABC")); | |
| writeln(numUpper(3, 2, "12ABC")); | |
| // Applicative | |
| // ditto : Just (+3) <*> Just 2 | |
| just(_.plus(3)).ap(just(2)).writeln; | |
| // ditto : fmap (+3) [1, 2, 3] | |
| list!(1, 2, 3).fmap(_.plus(3)).writeln; | |
| // ditto : [(*2), (+3)] <*> [1, 2, 3] | |
| list!((int x) => x * 2, (int x) => x + 3).ap(list!(1, 2, 3)).writeln; | |
| // ditto : <$> (Just 5) | |
| func((int x) => (int y) => x + y).fmap(just(5)).writeln; | |
| // ditto : Just (+5) <*> (Just 3) | |
| func((int x) => (int y) => x + y).fmap(just(5)).ap(just(3)).writeln; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Maybeまでなら書いたことがあります(Functorは実装してません).
どこにも公開してなかったので,ここに供養(不法投棄?)しようと思います.
ご迷惑じゃなければ参考にしてください.