Stream: beginners

Topic: ADTs in roc


view this post on Zulip Monica (Jul 28 2024 at 19:00):

Hey so I want to create an algebraic data type in roc like this:

Student : [
   Current,
   Graduated
]
Current : {
  name : Str,
  grade : U64
}
Graduated : {
  name : Str,
  finalGrade : U64
}

First question, is this the right way to define my ADT?

Second question, if yes to q1, why am I getting a type mismatch on the following function?

sumStudent : (Dict Str Json), Str -> Result Student JsonErrors
sumStudent =\d, name ->
    when Dict.get d "finalGrade" is
        Ok (Number fg) -> Ok ({ name: name, finalGrade: fg })
        _ -> when Dict.get d "grade" is
                  Ok (Number cg) -> Ok ({ name: name, grade: cg })
                  _ -> Err(FieldNotFound "found neither field")

(I basically want to return either of the sum type variants depending on if the field is a key in d)

Thanks in advance!

view this post on Zulip Tanner Nielsen (Jul 28 2024 at 19:18):

It's been awhile since I've written any Roc, but I think the problem here is that Roc doesn't have untagged unions. Student would need to be tagged union instead. So I think you probably want something like this:

Student : [
    Current {
        name : Str,
        grade : U64
    },
    Graduated {
        name : Str,
        finalGrade : U64
    }
]

Also here's the relevant section of the tutorial which covers tags with payloads: https://www.roc-lang.org/tutorial#tags-with-payloads

Hope that helps!

view this post on Zulip Monica (Jul 28 2024 at 19:19):

Ahhhh I tried

Student : [
    Current : {
        name : Str,
        grade : U64
    },
    Graduated : {
        name : Str,
        finalGrade : U64
    }
]

at first which didn't work

view this post on Zulip Monica (Jul 28 2024 at 19:25):

managed to make this work by doing the following:

sumStudent =\d, name ->
    when Dict.get d "finalGrade" is
        Ok (Number fg) -> Ok (Graduated { name: name, finalGrade: fg })
        _ -> when Dict.get d "grade" is
                  Ok (Number cg) -> Ok (Current { name: name, grade: cg })
                  _ -> Err(FieldNotFound "found neither field")

Thanks for your help!

view this post on Zulip Richard Feldman (Jul 28 2024 at 20:07):

nice! btw roc format will automatically normalize indentation and spaces and such

view this post on Zulip Monica (Jul 30 2024 at 08:21):

ah nice thanks for that!


Last updated: Jul 06 2025 at 12:14 UTC