Stream: beginners

Topic: working with type annotation problem


view this post on Zulip Artur Swiderski (Nov 25 2023 at 21:20):

hi
Working with type annotations is extremally frustrating I have spend two hours straight and I can't make working even simple thing, what to do here :

nodeType  :  { children : List (Num a), locked : Bool, value : List *} where a implements Hash & Eq
g  : List * -> nodeType
g  = \ lst ->
    { children : [], locked : Bool.true, value : [] }

view this post on Zulip Notification Bot (Nov 25 2023 at 21:20):

This topic was moved here from #beginners > working with type annotation by Artur Swiderski.

view this post on Zulip Artur Swiderski (Nov 25 2023 at 21:21):

why it does not compile how to fix it ?

view this post on Zulip Artur Swiderski (Nov 25 2023 at 21:23):

why it is so unintuitive and difficult ?

view this post on Zulip Luke Boswell (Nov 25 2023 at 21:49):

I can see a few issues with your example, its quite complex because it combines a lot of different features, and even includes some really advanced stuff like Abilities.

You're not asking me to help you with a working version, but you would like to know how to fix it.

I find it helpful to start with a really simple type annotation. Then run roc check to confirm it compiles like I expect. Then incrementally change it and re-run roc check. This way I get immediate feedback when I do something incorrectly and I know exactly where the issue is. In this way the compiler is a really helpful teacher for the type system. Also adding unit tests is another great way to check understanding of types.

view this post on Zulip Richard Feldman (Nov 25 2023 at 21:56):

one problem is that nodeType : is syntactically invalid because it's not capitalized. (I'm on mobile so not sure what the error message is, but I'm guessing it's not clear about this!)

It needs to be NodeType : rather than nodeType :

view this post on Zulip Richard Feldman (Nov 25 2023 at 22:08):

I notice some other problems:

  1. Whenever a type alias contains a type variable (lowercase names in type annotations, such as a, are always type variables), that variable must be listed next to the alias name. So since NodeType contains an a (specifically in Num a), it needs to be NodeType a :
  2. Type aliases can't contain *, you have to choose names for those type variables (such as a instead of *, although in this particular type, a is already being used for something else, so we'd probably want to replace the * with b). So it can't be value : List *, it has to be value: List b (and then NodeType a b : because b needs to be listed next to the alias name just like a did.)
  3. where a implements Hash & Eq applies to the a in Num a. I'm guessing that's not necessary and can be removed!

view this post on Zulip Brendan Hansknecht (Nov 26 2023 at 00:46):

These sound like good issues to track around improving our error massages to help make this experience nicer

view this post on Zulip Artur Swiderski (Nov 26 2023 at 02:32):

it works thx for tips @Richard Feldman , but this syntax is difficult nevertheless . Thankfully this is optional, if I have to keep track of those types during prototyping stage, it would be just to much. I hope it stays this way as -> optional feature

view this post on Zulip Andrew C (Nov 26 2023 at 15:15):

The FAQ says
"A valuable aspect of Roc's type system is that it has decidable principal type inference. This means that:

At compile time, Roc can correctly infer the types for every expression in a program, even if you don't annotate any of the types."

so I don't think that feature is going away. I think it's fairly fundamental to the design decisions behind the language.


Last updated: Jul 06 2025 at 12:14 UTC