Stream: beginners

Topic: Type alias question


view this post on Zulip Krzysztof Skowronek (Apr 15 2025 at 21:30):

I have the following sample:

module [MyType, create]

MyType : {
    name : Str,
}

# I know I can do this
# create : Str -> MyType
create = |name| {name}

Is there a way to "cast" the record to the alias without the global type annotation?

I guess the same goes for:

# a : MyType
a = {name: "name"} # can I somehow "cast" it?

I tried different things, but most errors point me to a situation where it just creates a new tag. Btw, I was a bit surprised that you can have both a tag and a type with the same name :)

view this post on Zulip Brendan Hansknecht (Apr 15 2025 at 23:59):

I'm not sure I understand the question. What do you need to cast?

view this post on Zulip Krzysztof Skowronek (Apr 16 2025 at 06:56):

I want the function type to say it return MyType. So I need to somehow tell the compiler to use the alias instead of just record shape.

So far only way I found is to use type annotations on the function. By casting I mean putting something in the record itself, so that the MyType is infected for the function

view this post on Zulip Krzysztof Skowronek (Apr 16 2025 at 08:45):

I am looking for something like:

create = |name| {name} as MyType

so that the create function is inferred as create: Str -> MyType instead of create : Str -> {name: Str}. I know I can add the dectoration on the fucntion. Another thing I know I can do is:

create = |name|
    result : MyType
    result = { name }

    result

but it still feels like a way around :)

view this post on Zulip Anton (Apr 16 2025 at 09:27):

There is no casting like that in Roc, annotations are the only way.

view this post on Zulip Anton (Apr 16 2025 at 10:09):

A function that returns { name: Str } and one that accepts MyType are compatible though.

view this post on Zulip Krzysztof Skowronek (Apr 16 2025 at 10:15):

I know, but they stop being compatible when I change the MyType definition. I guess type annotations are enough. the seem a bit invasive. But defintely good enough :)

view this post on Zulip Brendan Hansknecht (Apr 16 2025 at 17:09):

An important piece of information in Roc:
A type alias is solely an alias (or in more proper terms, is a structural type). So they have no distinction in the compiler from the underlying type. That is why you can't cast to them it would literally be a noop.

We also have opaque types (which are true custom types that are unique), but they are likely way more heavy handed than you want here.

Type annotations are the correct solution in roc for this.

The short way to do it without annotating the function would be to just annotate the variable:

myFn = |...|
    ...
    x : SomeType
    x = ...
    x

We generally recommend annotating all top level functions in code larger than small scripts.

view this post on Zulip Krzysztof Skowronek (Apr 16 2025 at 19:08):

I fully understand, I haven't written big enough program yet to fully emerge the practices around that :)

I have played with opaque types, and so far my only question for them would be whether it's possible to make just some member "public", like a length for a list while everything else is hidden.

Judging by the standard library it's impossible and I should just make MyType.len function

view this post on Zulip Brendan Hansknecht (Apr 16 2025 at 19:31):

Currently impossible. May change in the zig compiler with custom types (the new variant of opaque types)


Last updated: Jul 05 2025 at 12:14 UTC