Skip to content

Instantly share code, notes, and snippets.

@mike-neck
Created December 13, 2017 12:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mike-neck/28ab16b62f3b39fceeb7b180c7b42981 to your computer and use it in GitHub Desktop.
Save mike-neck/28ab16b62f3b39fceeb7b180c7b42981 to your computer and use it in GitHub Desktop.
Groovy で higher kind type を無理やり試してみる
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