Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to implement `Functor<T>` in Java?

I stumbled upon a little problem today. Consider a little wrapper class:

class Event<T> {
   T value;
   Class<T> type;
   // other fields, getters and setters omitted for brevity
}

Now I was in a situation where I wanted to convert a Event<Long> into a Event<String> while preserving the other fields and updating the type member.

Eventually I ended up with the most simple "solution":

Event<String> new = new Event(old.getValue().toString(), String.class, other, fields);

Having worked with Haskell on my pet projects however, I naturally longed for a function like fmap :: Functor f => (a -> b) -> f a -> f b (read: given a function from a to b and a functor containing something of type a give me a result containing the b) and after finding no standard implementation I set out to write one myself:

interface Functor<T> {
  Functor<S> fmap( Func1<T,S> f );
}

// ... in Event<T>:

Functor<S> fmap( Func1<T,S> f ) { 
  S newValue = f.call(this.value);
  return new Event( newValue, newValue.getClass(), other, fields);
}

Now there is a problem with this solution: after the call to fmap in Java I am left with an instance of type Functor<String> while the same function in Haskell would return a Event<String>.

Is there a way to get my Event back (without unsafely casting it)?

like image 918
fho Avatar asked Dec 19 '22 16:12

fho


1 Answers

No, it isn't possible. For this to happen we would need to abstract over the Functor in your interface, something like

interface Functor<T> as F<T> {
    F<S> map(f : Function<T, S>);
}

But Java doesn't allow you to abstract over type constructors, just types. This is called Higher Kinded Types (HKT). Only a few (non-dependent) languages have HKTs, Scala and Haskell are the only two I can think of.

In fact HKTs are necessary to express a lot of abstractions,

  1. Control.Monad
  2. Control.Applicative
  3. Data.Traversable
  4. Data.Foldable
  5. Control.Monad.Trans
  6. Any monad transformers, full stop
  7. Free monads
  8. Lenses/Prisms
  9. Streaming libraries (they're monad transformers)
  10. Almost everything that was in category-extras

All of these involve abstracting over type constructors, not just concrete types.

like image 84
Daniel Gratzer Avatar answered Dec 31 '22 16:12

Daniel Gratzer