Created
December 13, 2017 12:55
-
-
Save mike-neck/28ab16b62f3b39fceeb7b180c7b42981 to your computer and use it in GitHub Desktop.
Groovy で higher kind type を無理やり試してみる
This file contains 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
interface _0<M> {} | |
interface _1<M, A> extends _0<M> {} | |
interface _2<M, A, B> extends _1<_1<M, A>, B> {} | |
interface Eq<A> extends _1<Eq.M, A> { | |
final class M {} | |
boolean eq(A x, A y) | |
} | |
class IntEq implements Eq<Integer> { | |
private IntEq() {} | |
@Override | |
boolean eq(Integer x, Integer y) { x == y } | |
static final IntEq instance = new IntEq() | |
} | |
def i = IntEq.instance | |
assert i.eq(1, 1) | |
Integer.metaClass.define { | |
eq = {int other -> | |
IntEq.instance.eq(delegate, other) | |
} | |
} | |
assert 1.eq(2) == false | |
interface Functor<F> { | |
public <A, B> _1<F, B> fmap(_1<F, A> o, Closure<B> f) | |
} | |
interface Maybe<A> extends _1<Maybe.M, A> { | |
interface M {} | |
} | |
class Nothing<A> implements Maybe<A> { | |
static Nothing<?> instance = new Nothing() | |
private Nothing() {} | |
static <A> Nothing<A> nothing() { | |
instance as Nothing<A> | |
} | |
@Override String toString() { 'Nothing' } | |
@Override int hashCode() { 0 } | |
@Override boolean equals(def o) { o != null && o instanceof Nothing } | |
} | |
class Just<A> implements Maybe<A> { | |
final A value | |
Just(A value) { this.value = value } | |
@Override String toString() { "Just($value)" } | |
@Override int hashCode() { value.hashCode() } | |
@Override boolean equals(def o) { o != null && o instanceof Just && this.value.equals(o.value) } | |
} | |
class MaybeFunctor implements Functor<Maybe.M> { | |
static final MaybeFunctor instance = new MaybeFunctor() | |
private MaybeFunctor(){} | |
@Override | |
<A,B> _1<Maybe.M, B> fmap(_1<Maybe.M, A> o, Closure<B> f) { | |
if (o instanceof Just) { | |
new Just(f(o.value)) | |
} else { | |
Nothing.instance as Maybe<B> | |
} | |
} | |
} | |
Maybe.metaClass.define { | |
fmap = {Closure c -> | |
MaybeFunctor.instance.fmap(delegate, c) | |
} | |
} | |
def nothing = Nothing.<String>nothing() | |
def nmap = nothing.fmap { it.length() } | |
assert nmap == nothing | |
def just = new Just('Foo') | |
def mapped = just.fmap { it.toUpperCase() } | |
assert mapped.value == 'FOO' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment