Reputation: 897
In Haskell, we can define types with multiple, mutually exclusive value constructors, such as the Maybe type, which is defined as follows:
data Maybe a = Nothing | Just a
where 'a' is any existing type. It'd be nice if we could do something similar in Java. For instance, if we wanted to define an extended real number in Haskell, we could do something like
data ExtendedReal = Infinity | Real Double
In Java, the only way I can think of creating a class with similar functionality is by putting a boolean flag in the class that overrides the double. For instance, we could do
public class ExtendedReal {
private double real;
private boolean isInfinity;
public ExtendedReal() {
isInfinity = true;
}
public ExtendedReal(double real) {
this.real = real;
}
...
...
}
and then check for the flag in all of your methods.
Is there a more canonical way of achieving this?
Upvotes: 1
Views: 169
Reputation: 691943
Not sure if this really answers your question, because I'm not familiar with Haskell, and I'm not sure I really understand the question, but "special cases" like this can be designed as a base class with subclasses, and polymorphism:
public abstract class Real {
public abstract Real plus(double value);
public static Real infinity() {
return new Infinity();
}
public static Real regular(double value) {
return new RegularReal(value);
}
private static class Infinity extends Real {
@Override
public void plus(double value) {
return this;
}
}
private static class RegularReal extends Real {
private final double value;
private RegularReal(double value) {
this.value = value;
}
@Override
public Real plus(double value) {
return new RegularReal(this.value + value);
}
}
}
Upvotes: 4
Reputation: 8200
AFAIK Java 8's Optional
is somewhat similar to Haskell's Maybe. Since Java's Optional is implemented using if/else, I guess this is the way to do it in Java. Of course, it is possible to replace that with polymorphism, but the principle remains. For example, Optional's map function is implemented this way:
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Optional.ofNullable(mapper.apply(value));
}
}
public boolean isPresent() {
return value != null;
}
Upvotes: 0
Reputation: 2203
One possible way to achieve this for immutable classes is to define public static final instances of the class that represent special values. With this approach no new types are introduced.
Upvotes: 0