Stream: beginners

Topic: ✔ Struggling with type inference for expect / tests


view this post on Zulip Fábio Beirão (Jun 07 2023 at 17:55):

I'm a bit struggling with creating an interface for a "generic Stack" (regardless of whether it already exists in a package or not, I'm trying to create my own for educational purposes)

If I have the two expect at the bottom uncommented at the same time, roc check stops being my friend.
And if I have one of the expect uncommented, and I add the type signature to empty (I think the type would be empty : Stack *, then roc check also stops being my friend.

interface Stack
    exposes [
        Stack,
        empty,
        withCapacity,
        isEmpty,
        top,
        put,
        pop,
    ]
    imports []

Stack a := List a

# 👇 If I uncoment this type annotation (together with one of the tests below), then roc check is no longer happy

#empty : Stack *
empty = fromList []

fromList : List a -> Stack a
fromList = \list -> @Stack list

withCapacity : Nat -> Stack a
withCapacity = \elements ->
    @Stack (List.withCapacity elements)

isEmpty : Stack * -> Bool
isEmpty = \@Stack stack ->
    stack |> List.isEmpty

top : Stack a -> Result a [StackWasEmpty]
top = \@Stack stack ->
    stack |> List.last |> Result.mapErr (\_ -> StackWasEmpty)

put : Stack a, a -> Stack a
put = \@Stack stack, elem ->
    @Stack (stack |> List.append elem)

pop : Stack a -> Result { elem : a, stack : Stack a } [StackWasEmpty]
pop = \@Stack stack ->
    when (stack |> List.last) is
        Ok elem -> Ok { elem, stack: @Stack (stack |> List.dropLast) }
        Err ListWasEmpty -> Err StackWasEmpty

expect (empty |> isEmpty) == Bool.true

## 👇 I can't have these two uncommented at the same time 😖

expect (empty |> put 1 |> put 2 |> pop |> Result.map .elem) == Ok 2
#expect (empty |> put "A" |> put "B" |> pop |> Result.map .elem) == Ok "B"

This is the nightly version of roc. Am I doing something impossible, or is this a well-known issue?

view this post on Zulip Brendan Hansknecht (Jun 07 2023 at 18:04):

Empty needs to be a function

view this post on Zulip Brendan Hansknecht (Jun 07 2023 at 18:04):

Then it would be used as empty {}

view this post on Zulip Brendan Hansknecht (Jun 07 2023 at 18:04):

To create a new empty stack

view this post on Zulip Fábio Beirão (Jun 07 2023 at 18:04):

Yeah, I'm looking at Dict, and indeed, Dict.empty is also used as Dict.empty {}

view this post on Zulip Fábio Beirão (Jun 07 2023 at 18:05):

Ok, let me make some adjustments :D :sweat_smile:

view this post on Zulip Fábio Beirão (Jun 07 2023 at 18:07):

:tada: As a wise man used to say, "There's nothing like speaking with those who know". Thanks @Brendan Hansknecht that was the solution :pray::pray:

view this post on Zulip Notification Bot (Jun 07 2023 at 18:07):

Fábio Beirão has marked this topic as resolved.

view this post on Zulip Brendan Hansknecht (Jun 07 2023 at 18:09):

@Ayaz Hafiz do you think there is a way for the compiler to give a better error message related to this and #ideas > Let-generalization - let's not? ? Should we file an issue for clarity in the error message here or would that not really be possible?

view this post on Zulip Ayaz Hafiz (Jun 07 2023 at 18:16):

yeah, we should definitely give better error messages. There's a section in the "Let's not?" doc that describes how we can do it, so that can be referenced in the issue

view this post on Zulip Brendan Hansknecht (Jun 07 2023 at 18:21):

Can you write up the issue since you have more context?

view this post on Zulip Ayaz Hafiz (Jun 07 2023 at 18:28):

sure, will do


Last updated: Jul 06 2025 at 12:14 UTC