unisonweb-org icon indicating copy to clipboard operation
unisonweb-org copied to clipboard

Error in the stream example of the abilities section

Open maxtremblay opened this issue 3 years ago • 3 comments

While reading the Abilities in Unison section, I tried to run the following example:

structural ability Stream e where
  emit : e ->{Stream e} ()
  -- equivalently
  -- emit : e -> ()

Stream.range : Nat ->{} Nat ->{Stream Nat} ()
Stream.range n m =
  if n >= m then ()
  else
    emit n
    Stream.range (n + 1) m

However, I got the following error

The else clause of an if expression needs to
  have the same type as the then clause.

  Here, one   is:  Unit
  and another is:  Unit ->{Stream Nat} Unit


      8 |   if n >= m then ()
      9 |   else
     10 |     emit n
     11 |     Stream.range (n + 1) m

From the error message, I figured out I can replace the last line of the range definition by

Stream.range (n + 1) m ()

but this seems weird to me.

In case this is helpful, I am running release/M2j (built on 2021-10-07).

maxtremblay avatar Nov 07 '21 13:11 maxtremblay

@maxtremblay for me (also on release/M2j) I can't reproduce this locally , but I suspect that I know what's going on.

Do you have all of this code within the same scratch file and are adding it all at once? When I do this it works as expected.

But what I think is happening is that your else clause is somehow picking up .base.Stream.range, which is defined as:

.base.Stream.range : Nat -> Nat -> '{Stream Nat} ()
.base.Stream.range n m _ = Stream.range! n m

This would explain why it's expecting you to force the delayed thunk with (). What isn't clear to me is why it would pick up the Stream.range from base instead of the one that you are declaring. If you are able to create a transcript that reproduces this issue, that would be very helpful!

ceedubs avatar Nov 11 '21 19:11 ceedubs

There it is.

transcript.md

maxtremblay avatar Nov 11 '21 21:11 maxtremblay

@maxtremblay thank you! I now see the behavior that you were talking about.

If I remove the use .base then it works just fine. But the Stream.range that's being defined should be prioritized over the one coming from .base. So this does seem like a bug, and worse, one that users can run into while going through the intro docs. @pchiusano or @runarorama do either of you know what's going on here?

ceedubs avatar Nov 11 '21 22:11 ceedubs