Skip to content

Deep structural pattern matching #8

@nobeh

Description

@nobeh

Let's consider the following naive example:

  static interface Map_<A, B> {
  }

  static class EmptyMap_<A, B> implements Map_<A, B> {
  }

  static class InsertAssoc_<A, B> implements Map_<A, B> {
    public final Pair<A, B> pair;
    public final Map_<A, B> map;

    public InsertAssoc_(Pair<A, B> pair, Map_<A, B> map) {
      this.pair = pair;
      this.map = map;
    }
  }

and now I'd like to define a method put with the following logic:

  public static <A, B> Map_<A, B> put_(final Map_<A, B> ms, final A k, final B v) {
    if (ms instanceof EmptyMap_ || ms == null) {
      return new InsertAssoc_(Pair(k, v), new EmptyMap_<>());
    }
    if (ms instanceof InsertAssoc_) {
      InsertAssoc_<A, B> is = (InsertAssoc_<A, B>) ms;
      if (k.equals(is.pair.getFirst())) {
        return new InsertAssoc_<>(Pair(k, v), is.map);
      } else {
        return new InsertAssoc_<>(Pair(k, v), put_(is.map, k, v));
      }
    }
    throw new IllegalArgumentException();
  }

Trying to do it with Motif as the following leads to compile errors:

  public static <A, B> Map_<A, B> put_motif(final Map_<A, B> ms, final A k, final B v) {
    match((Map_<A, B>) ms).when(caseThat(isA(EmptyMap_.class)))
        .get(x -> new InsertAssoc_<>(Pair(k, v), new EmptyMap_<>()))
        .when(caseThat(isA(InsertAssoc_.class)))
        .get((InsertAssoc_ x) -> k.equals(x.pair.getFirst()) ? new InsertAssoc_<>(Pair(k, v), x.map)
            : new InsertAssoc_<>(Pair(k, v), put_motif(x.map, k, v)));;
    return null;
  }

and the compilation error is basically type mismatch. In this example, I am trying to use Hamcrest matchers. Is there another way? What's the correct way to do this in Motif?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions