I'm trying to define classes in Java that are similar to Haskell's functors. Hereby, a functor is defined as:
/**
* Programming languages allow only (just simply enough) endofunctor, that are functors from and to the same category.
* In this case, the category is the one of the datatypes (in here Type, in order to make it more clear)
*/
public interface EndoFunctor<X extends Type> extends Type {
/**
* The basic implementation for any element fx
* @param map Transformation function for the type parameter
* @param fx Element of the current class
* @param <Y> Target type
* @return transformed element through map
*/
<Y extends Type> EndoFunctor<Y> fmap(Function<X,Y> map, EndoFunctor<X> fx);
}
If I want to implement a functor, I have to write something like
public class Id<X extends Type> implements EndoFunctor<X> {
protected X witness;
Id(X witness) { this.witness = witness; }
@Override
public <Y extends Type> Id<Y> fmap(Function<X, Y> map, Id<X> fx) {
return new Id<>(map.apply(fx.witness));
}
}
The problem with this code is that Id<X>
does not match the type EndoFunctor<X>
. How could I determine fmap
in the EndoFunctor
interface such that if any type K<T>
implements EndoFunctor<T>
and a map function T->U
is given, then K<U>
is returned as a value, without any typecasting (that is, since I know that my object is an Id<T>
, then the result of fmap
"has to be" a Id<U>
, and hence I downcast the result of type EndoFunctor<U>
to such type)?
A functor (or function object) is a C++ class that acts like a function. Functors are called using the same old function call syntax. To create a functor, we create a object that overloads the operator().
In functional programming, a functor is a design pattern inspired by the definition from category theory, that allows for a generic type to apply a function inside without changing the structure of the generic type. This idea is encoded in Haskell using type class.
In computer programming, a function object is a construct allowing an object to be invoked or called as if it were an ordinary function, usually with the same syntax (a function parameter that can also be a function). Function objects are often called functors.
An array is a good example of a functor, but many other kinds of objects can be mapped over as well, including promises, streams, trees, objects, etc. JavaScript's built in array and promise objects act like functors.
You could use CRTP:
interface EndoFunctor<X extends Type, T extends EndoFunctor<X, T>> extends Type {
<Y extends Type> EndoFunctor<Y, ?> fmap(Function<X,Y> map, T fx);
}
class Id<X extends Type> implements EndoFunctor<X, Id<X>> {
protected X witness;
Id(X witness) { this.witness = witness; }
@Override
public <Y extends Type> Id<Y> fmap(Function<X, Y> map, Id<X> fx) {
return new Id<>(map.apply(fx.witness));
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With