# How to pattern match over type unions?

**URL:** <https://forum.dfinity.org/t/how-to-pattern-match-over-type-unions/11008>\
**Category:** Language Support\
**Tags:** Motoko\
**Created:** [February 21, 2022, 1:17am UTC](https://forum.dfinity.org/t/how-to-pattern-match-over-type-unions/11008 "2022-02-21T01:17:47Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![icme](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/icme/32/4327_2.png) [@icme](https://forum.dfinity.org/u/icme)\
**Post date:** [February 21, 2022, 1:17am UTC](https://forum.dfinity.org/t/how-to-pattern-match-over-type-unions/11008/1 "2022-02-21T01:17:48Z")

</div>

Super excited to be using type unions in the 0.9.0 release - thanks guys!

Would it be possible to include some examples in the [Union Type docs](https://smartcontracts.org/docs/language-guide/language-manual.html#or-type) on how one might go about pattern matching over type unions, where these examples include cases resulting in None/Any or some overlap?

It’s a bit difficult for me to decipher through [the commit where this was introduced](https://github.com/dfinity/motoko/commit/de00655a0838b4799a6c24a6074ba6e534e47275) to understand how I might do this.

A basic example:

```auto
type JSON = Nat or Text or HashMap or ...;

func toJSON(json: JSON): Text {
  switch(json) {
    case Nat n { ... };
    case Text t { ... };
    case HashMap hm { ... this could be recursive and call toJSON depending on the k/v type };
  }
}

```

I’ve seen [an implementation of this that works](https://github.com/aviate-labs/json.mo/blob/main/src/JSON.mo), which is very similar to the answer given out last year in this forum post [https://forum.dfinity.org/t/pattern-matching-with-dynamic-case/5139](https://forum.dfinity.org/t/pattern-matching-with-dynamic-case/5139), but requires the use of variants and wrapping all the values in the variant as they are stored.

Is there a more elegant solution that type unions might provide?

---

<div class="post-metadata">

**Author:** ![paulyoung](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/paulyoung/32/5251_2.png) [@paulyoung](https://forum.dfinity.org/u/paulyoung)\
**Post date:** [February 21, 2022, 3:25am UTC](https://forum.dfinity.org/t/how-to-pattern-match-over-type-unions/11008/2 "2022-02-21T03:25:36Z")

</div>

I don’t believe you can since, as the documentation you linked to says, you’re effectively pattern matching on a value whose type is `Any`.

---

<div class="post-metadata">

**Author:** ![icme](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/icme/32/4327_2.png) [@icme](https://forum.dfinity.org/u/icme)\
**Post date:** [February 21, 2022, 5:19am UTC](https://forum.dfinity.org/t/how-to-pattern-match-over-type-unions/11008/3 "2022-02-21T05:19:52Z")

</div>

If this is the case, then where does the value from type unions come in? Under what scenarios would it make more sense to choose to use a type union over a predetermined wrapped variant type?

---

<div class="post-metadata">

**Author:** ![paulyoung](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/paulyoung/32/5251_2.png) [@paulyoung](https://forum.dfinity.org/u/paulyoung)\
**Post date:** [February 21, 2022, 5:21am UTC](https://forum.dfinity.org/t/how-to-pattern-match-over-type-unions/11008/4 "2022-02-21T05:21:21Z")

</div>

Here’s an old example:

> <https://github.com/dfinity/motoko/issues/66>
>
> Given something like the following:
> 
> \`\`\`swift
> type Foo = { foo : Text };
> typ…e Bar = { bar : Text };
> \`\`\`
> 
> Is it possible to represent the union of \`Foo\` and \`Bar\` at the type level, in an ad hoc manner and without defining \`FooAndBar\`?
> 
> \`\`\`swift
> type FooAndBar = { foo : Text, bar : Text };
> \`\`\`

---

<div class="post-metadata">

**Author:** ![icme](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/icme/32/4327_2.png) [@icme](https://forum.dfinity.org/u/icme)\
**Post date:** [February 21, 2022, 5:29am UTC](https://forum.dfinity.org/t/how-to-pattern-match-over-type-unions/11008/5 "2022-02-21T05:29:33Z")

</div>

That example seems to ask for an intersection type, as opposed to a union type.

I’m imagining something like shown here in Elm lang that allows for destructuring based on types. It’s extremely powerful.

[https://guide.elm-lang.org/types/pattern\_matching.html](https://guide.elm-lang.org/types/pattern_matching.html)

---

<div class="post-metadata">

**Author:** ![paulyoung](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/paulyoung/32/5251_2.png) [@paulyoung](https://forum.dfinity.org/u/paulyoung)\
**Post date:** [February 21, 2022, 5:32am UTC](https://forum.dfinity.org/t/how-to-pattern-match-over-type-unions/11008/6 "2022-02-21T05:32:03Z")

</div>

> [@icme](#):
>
> That example seems to ask for an intersection type, as opposed to a union type.

Right, but the same thing applies. You have some existing types and want to say “this or that”/“this and that” without having to create a new named type.

As the documentation says, it’s more useful when the types are compatible through sub typing.

---

<div class="post-metadata">

**Author:** ![paulyoung](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/paulyoung/32/5251_2.png) [@paulyoung](https://forum.dfinity.org/u/paulyoung)\
**Post date:** [February 21, 2022, 5:36am UTC](https://forum.dfinity.org/t/how-to-pattern-match-over-type-unions/11008/7 "2022-02-21T05:36:08Z")

</div>

The equivalent of this Elm code:

```auto
type User
  = Regular String Int
  | Visitor String

```

In Motoko is this variant:

```auto
type User = {
  #Regular : (Text, Int);
  #Visitor : Text;
};

```

---

<div class="post-metadata">

**Author:** ![icme](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/icme/32/4327_2.png) [@icme](https://forum.dfinity.org/u/icme)\
**Post date:** [February 21, 2022, 5:40am UTC](https://forum.dfinity.org/t/how-to-pattern-match-over-type-unions/11008/8 "2022-02-21T05:40:55Z")

</div>

I see, ok so then type ~~unions~~ **intersections** essentially favor the creation of new types through composition/reuse of smaller types. I’m assuming these would be usually combination of record types, for example something like:

```auto
type UserPermissions = {
  #createPost;
  #editPost;
  #deletePost;
  ...
};
type AdminPermissions = {
  #banUser;
  #createChannel;
} and UserPermissions;

```

---

<div class="post-metadata">

**Author:** ![icme](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/icme/32/4327_2.png) [@icme](https://forum.dfinity.org/u/icme)\
**Post date:** [February 21, 2022, 5:42am UTC](https://forum.dfinity.org/t/how-to-pattern-match-over-type-unions/11008/9 "2022-02-21T05:42:23Z")

</div>

> The equivalent of this Elm code: …

Got it, makes sense. So the variant pattern is the way to go then.

Thanks for the responses and help!

---

<div class="post-metadata">

**Author:** ![paulyoung](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/paulyoung/32/5251_2.png) [@paulyoung](https://forum.dfinity.org/u/paulyoung)\
**Post date:** [February 21, 2022, 5:47am UTC](https://forum.dfinity.org/t/how-to-pattern-match-over-type-unions/11008/10 "2022-02-21T05:47:51Z")

</div>

An important distinction is that these are variants, which are sum types (“this _or_ this _or_…“) whereas records are product types (“this _and_ this _and_…”)

Also, I suspect you meant `and UserPermissions` so that admin users have at least the same permissions as regular users.

---

<div class="post-metadata">

**Author:** ![icme](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/icme/32/4327_2.png) [@icme](https://forum.dfinity.org/u/icme)\
**Post date:** [February 21, 2022, 6:01am UTC](https://forum.dfinity.org/t/how-to-pattern-match-over-type-unions/11008/11 "2022-02-21T06:01:28Z")

</div>

Oops, yes you’re right! Edited the above to not fool anyone who comes across this in the future.

> [@paulyoung](#):
>
> An important distinction is that these are variants, which are sum types (“this _or_ this _or_ …“) whereas records are product types (“this _and_ this _and_ …”)

This is a great mental model 💡

Ok I’m a huge fan of variants now, the lights are on 😄
