# Recursive type clarification

**URL:** <https://discourse.elm-lang.org/t/recursive-type-clarification/9667>\
**Category:** Learn\
**Created:** [February 19, 2024, 1:47am UTC](https://discourse.elm-lang.org/t/recursive-type-clarification/9667 "2024-02-19T01:47:33Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![kuna.prime](https://avatars.discourse-cdn.com/v4/letter/k/b77776/32.png) [@kuna.prime](https://discourse.elm-lang.org/u/kuna.prime)\
**Post date:** [February 19, 2024, 1:47am UTC](https://discourse.elm-lang.org/t/recursive-type-clarification/9667/1 "2024-02-19T01:47:33Z")

</div>

Hi there,  
I’m trying to work out how to make my first elm app and i’m going through some examples on web. I have encountered this definition

```elm
type Avatar
    = Avatar (Maybe String)

```

how does one read this and what does it mean? does this pattern have specific name?

---

<div class="post-metadata">

**Author:** ![ErikF](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/erikf/32/2643_2.png) [@ErikF](https://discourse.elm-lang.org/u/ErikF)\
**Post date:** [February 19, 2024, 3:22am UTC](https://discourse.elm-lang.org/t/recursive-type-clarification/9667/2 "2024-02-19T03:22:49Z")

</div>

Hello there!

What you are looking at is what we call a [Custom Type](https://guide.elm-lang.org/types/custom_types). They can be recursive, but this one is not.

A way to read it goes something like this. `type Avatar` is saying I am creating a new type called "Avatar’. `= Avatar (Maybe String)` is saying a few things. First it is saying we only have one “variant”. Next it is saying what the name of the type constructor is (in this case its Avatar but it does not need to match the type name). And lastly it is saying that Avatar “holds” `(Maybe String)`

Id recommended checking out the link to Custom Types above, and also tossing that type into `elm repl` and playing around with it 🙂.

---

<div class="post-metadata">

**Author:** ![Lucas\_Payr](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/lucas_payr/32/4993_2.png) [@Lucas\_Payr](https://discourse.elm-lang.org/u/Lucas_Payr)\
**Post date:** [February 19, 2024, 4:39am UTC](https://discourse.elm-lang.org/t/recursive-type-clarification/9667/3 "2024-02-19T04:39:51Z")

</div>

I would read it like "type `Avatar` has a constructor called `Avatar` that takes `Maybe String` as an argument.

So it’s similarly to object-oriented languages, where the class constructor has the same name as the class. In java I would write: `Avatar avatar = new Avatar(stringOrNull)`

---

<div class="post-metadata">

**Author:** ![kuna.prime](https://avatars.discourse-cdn.com/v4/letter/k/b77776/32.png) [@kuna.prime](https://discourse.elm-lang.org/u/kuna.prime)\
**Post date:** [February 19, 2024, 11:09am UTC](https://discourse.elm-lang.org/t/recursive-type-clarification/9667/4 "2024-02-19T11:09:27Z")

</div>

so if i understand correctly here, type definition is collection of functions that result in that type. In other words all the way in which type can be constructed.

in this case it would be only one function `(Maybe String) -> Avatar`, however i still have a problem with "visualizing " shape of `Avatar`.

my formal FP is obviously not that strong so i would appreciate very much if someone can point to some resources where i could better understand mechanism, how is elm tracking which constructor is used and such.

thank you very much for help so far

---

<div class="post-metadata">

**Author:** ![Lucas\_Payr](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/lucas_payr/32/4993_2.png) [@Lucas\_Payr](https://discourse.elm-lang.org/u/Lucas_Payr)\
**Post date:** [February 19, 2024, 11:44am UTC](https://discourse.elm-lang.org/t/recursive-type-clarification/9667/5 "2024-02-19T11:44:17Z")

</div>

> [@kuna.prime](#):
>
> so if i understand correctly here, type definition is collection of functions that result in that type. In other words all the way in which type can be constructed.

Yes. exatly. Though it does not have to be functions.

Let’s look at `Bool` for a sec:

```auto
type Bool
  = True
  | False

```

So Bool can either be `True` or `False`. (The symobl `|` is read as “or”) That’s the structure of `Bool`.

Where as for `Maybe a` the definiton is

```auto
type Maybe a
  = Just a
  | Nothing

```

So the structure behind it is either `Nothing`, or (`Just` something).

`Just` itself is also a function. `Just:a -> Maybe` So depending on how you look on it. its either “How do i construct this type?” or “What shape can this type be?”.

* * *

Now back to the Avatar.

```auto
type MyAvatar
  = AvatarByName (Maybe String)

```

So Avatar is defined by its name. So the structure of the Avatar is its name.

---

<div class="post-metadata">

**Author:** ![kuna.prime](https://avatars.discourse-cdn.com/v4/letter/k/b77776/32.png) [@kuna.prime](https://discourse.elm-lang.org/u/kuna.prime)\
**Post date:** [February 19, 2024, 12:02pm UTC](https://discourse.elm-lang.org/t/recursive-type-clarification/9667/6 "2024-02-19T12:02:10Z")

</div>

would than `True` and `False` be constructors for `Bool`?

---

<div class="post-metadata">

**Author:** ![Lucas\_Payr](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/lucas_payr/32/4993_2.png) [@Lucas\_Payr](https://discourse.elm-lang.org/u/Lucas_Payr)\
**Post date:** [February 19, 2024, 12:07pm UTC](https://discourse.elm-lang.org/t/recursive-type-clarification/9667/7 "2024-02-19T12:07:55Z")

</div>

Yes.

You might ask “arn’t constructors always functions?” and you are right. But functions don’t need arguments.

You could say “`True` is a function with no argument”. If you come from typescript, this might look familiar:

```javascript
type Bool = "True" | "False"

function True(){return "True"}

function False(){return "False"}

```

In Elm functions with no arguments and constants are the same thing.

---

<div class="post-metadata">

**Author:** ![kuna.prime](https://avatars.discourse-cdn.com/v4/letter/k/b77776/32.png) [@kuna.prime](https://discourse.elm-lang.org/u/kuna.prime)\
**Post date:** [February 19, 2024, 12:27pm UTC](https://discourse.elm-lang.org/t/recursive-type-clarification/9667/8 "2024-02-19T12:27:37Z")

</div>

That makes sense.

In other languages types are collections of things, usually other types and from this is seems that in elm one construct the type in “reverse”, meaning you declare pathways in which you arrive to the type.

@Lucas_Payr thak you once agan

---

<div class="post-metadata">

**Author:** ![Lucas\_Payr](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/lucas_payr/32/4993_2.png) [@Lucas\_Payr](https://discourse.elm-lang.org/u/Lucas_Payr)\
**Post date:** [February 20, 2024, 7:04am UTC](https://discourse.elm-lang.org/t/recursive-type-clarification/9667/9 "2024-02-20T07:04:07Z")

</div>

Yeah. I think you got it. But I want to give one more example to really show what’s happening under the hood:

```auto
type Avatar
  = Guest
  | Regular String
  | Admin {name: String, role:String}

```

Let’s try to implement the same type in Typescript:

```auto
type AvatarVariant = "Guest" | "Regular" | "Admin"

interface Avatar { variant : AvatarVariant }

interface Guest extends Avatar {}
interface Regular extends Avatar {name:String}
interface Admin extends Avatar {
  name:String;
  role:String;
}

function Guest() : Guest {
  return {variant : "Guest"}
}

function Regular(name:String) : Regular {
  return {variant: "Regular", name: name}
}

function Admin(name:String,role:String) : Admin {
  return {variant: "Admin", name: name, role: role} 
}

```

---

<div class="post-metadata">

**Author:** ![kuna.prime](https://avatars.discourse-cdn.com/v4/letter/k/b77776/32.png) [@kuna.prime](https://discourse.elm-lang.org/u/kuna.prime)\
**Post date:** [February 20, 2024, 10:52am UTC](https://discourse.elm-lang.org/t/recursive-type-clarification/9667/10 "2024-02-20T10:52:06Z")

</div>

@Lucas_Payr thank you once again this is very helpful!

---

<div class="post-metadata">

**Author:** ![rupert](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/rupert/32/1775_2.png) [@rupert](https://discourse.elm-lang.org/u/rupert)\
**Post date:** [February 20, 2024, 11:24am UTC](https://discourse.elm-lang.org/t/recursive-type-clarification/9667/11 "2024-02-20T11:24:40Z")

</div>

I haven’t seen an actual recursive type yet in this thread, so thought I would give an example of one whilst hopefully not causing any confusion… Recursive types are very useful for building data structures.

You could define your own list type like this:

```auto
type MyList a
    = Nil
    | Cons a (MyList a)

```

Note that the type itself (MyList) appears in constructor argument position under Cons.

Also worth noting that you can only make recursive `type`s in Elm, and you cannot make a recursive `type alias`:

```auto
type alias MyList a =
    { cons : Maybe (a, MyList a) }

-- ALIAS PROBLEM ---------------------------------------------------------- REPL

This type alias is recursive, forming an infinite type!

2| type alias MyList a =
              ^^^^^^
When I expand a recursive type alias, it just keeps getting bigger and bigger.
So dealiasing results in an infinitely large type! Try this instead:

    type MyList a =
        MyList
            { cons : Maybe ( a, MyList a ) }

Hint: This is kind of a subtle distinction. I suggested the naive fix, but I
recommend reading <https://elm-lang.org/0.19.1/recursive-alias> for ideas on how
to do better.

```

---

<div class="post-metadata">

**Author:** ![system](https://canada1.discourse-cdn.com/flex035/uploads/elm_lang/original/1X/50a05e53677a2c3b47776d7abd0f113eb50193a1.png) [@system](https://discourse.elm-lang.org/u/system)\
**Post date:** [March 1, 2024, 11:25am UTC](https://discourse.elm-lang.org/t/recursive-type-clarification/9667/12 "2024-03-01T11:25:25Z")

</div>

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.
