Stream: beginners

Topic: ✔ Is this a bug in Roc or an EBKAC?


view this post on Zulip Francois Green (Jul 10 2024 at 02:29):

I tried moving an old F# (and OCaml before that ) lesson I found on the web to Roc:

let data = [4; 3; 8; 7; 10; 1; 9; 6; 5; 0; 2]

type Tree<'a> =
    | Node of Tree<'a> * 'a * Tree<'a>
    | Leaf

let rec insert tree element =
    match element, tree with
    | x, Leaf                       -> Node (Leaf, x, Leaf)
    | x, Node (l, y, r) when x <= y -> Node ((insert l x), y, r)
    | x, Node (l, y, r) when x > y  -> Node (l, y, (insert r x))
    | _ -> Leaf

let tree = List.fold insert Leaf data

let rec find goal queue =
    match queue with
    | [] -> None
    | (Leaf, _)::tail -> find goal tail
    | (Node (l, y, r), trace)::tail ->
        if y = goal then
            Some (List.rev (y::trace))
        else
            find goal (tail @ [l, y::trace; r, y::trace])

printfn "%A" (find 5 [tree, []])

The above works, but my Roc version gives me an error:

app [main] {
    pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.10.0/vNe6s9hWzoTZtFmNkvEICPErI9ptji_ySjicO6CkucY.tar.br",
}

import pf.Stdout

data = [4, 3, 8, 7, 10, 1, 9, 6, 5, 0, 2]

Tree a : [Node (Tree a, a, Tree a), Leaf]

insert = \tree, element ->
    when (element, tree) is
        (x, Leaf)                     -> Node (Leaf, x, Leaf)
        (x, Node (l, y, r)) if x <= y -> Node ((insert l x), y, r)
        (x, Node (l, y, r)) if x > y  -> Node (l, y, (insert r x))
        _ -> Leaf

boom = List.walk data Leaf insert

find = \goal, queue ->
    when queue is
        [] -> None
        [(Leaf, _), .. as tail] -> find goal tail
        [(Node (l, y, r), trace), .. as tail] ->
            if y == goal then
                Some (List.reverse (List.prepend trace y))
            else
                find goal (List.concat tail [(l, List.prepend trace y), (r, List.prepend trace y)])

main =

    Stdout.line "$(Inspect.toStr (find 5 [boom, []] ))"
TYPE MISMATCH

This list contains elements with different types:

32│      Stdout.line "$(Inspect.toStr (find 5 [boom, []] ))"
                                                     ^^

Its 2nd element is a list of type:

    List *

However, the 1st element has the type:

    [
        Leaf,
        Node (
            a,
            Num *,
            a,
        )c,
    ] as a

Every element in a list must have the same type!

Any help would be greatly appreciated.

view this post on Zulip Sam Mohr (Jul 10 2024 at 02:31):

If you move the boom definition inside of main, does it work?

view this post on Zulip Sam Mohr (Jul 10 2024 at 02:33):

That didn't work for me, ignore it

view this post on Zulip Sam Mohr (Jul 10 2024 at 02:33):

Thanks for posting the whole function, let me see if I can figure out what the issue is

view this post on Zulip Luke Boswell (Jul 10 2024 at 02:37):

I find adding type annotations to "pin" the types can help sometimes. Like it enables the compiler to find the issue sooner, or provide a better error message.

view this post on Zulip Sam Mohr (Jul 10 2024 at 02:37):

Yeah, that's what I'm doing

view this post on Zulip Luke Boswell (Jul 10 2024 at 02:39):

Could you define an fn and use that instead of []?

empty : Tree a
empty = []

view this post on Zulip Sam Mohr (Jul 10 2024 at 02:43):

Yeah, with doing that, I found two things:

find : Num a, List (Tree (Num a)) -> [Some (Num a), None]
find = \goal, queue ->
    when queue is
        [] -> None
        [(Leaf, _), .. as tail] -> find goal tail
        [(Node (l, y, r), trace), .. as tail] ->
            if y == goal then
                Some (List.reverse (List.prepend trace y))
            else
                find goal (List.concat tail [(l, List.prepend trace y), (r, List.prepend trace y)])

gives 4 errors, one of which is:

── TYPE MISMATCH in test.roc ───────────────────────────────────────────────────

This 2nd argument to find has an unexpected type:

26│                  find goal (List.concat tail [(l, List.prepend trace y), (r, List.prepend trace y)])
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

This concat call produces:

    List (
        *,
        List (Num a),
    )b

But find needs its 2nd argument to be:

    List [
        Leaf,
        Node (
            a,
            Num a,
            a,
        )b,
    ] as a

view this post on Zulip Sam Mohr (Jul 10 2024 at 02:46):

find : a, List (Tree a) -> [Some a, None] where a implements Eq

is a better type annotation btw

view this post on Zulip Brendan Hansknecht (Jul 10 2024 at 03:02):

I'm sure I'm missing something, but how is [boom, []] expected to typecheck? Isn't boom a Tree I64 while [] is a List *?

view this post on Zulip Brendan Hansknecht (Jul 10 2024 at 03:04):

Maybe it should be just [boom] or [boom, Leaf]?

view this post on Zulip Brendan Hansknecht (Jul 10 2024 at 03:09):

Oh, I think there is a tuple missing cause F# uses , for tuples and ; for lists

view this post on Zulip Brendan Hansknecht (Jul 10 2024 at 03:10):

    Stdout.line "$(Inspect.toStr (find 5 [(boom, [])]))"

view this post on Zulip Brendan Hansknecht (Jul 10 2024 at 03:10):

That runs for me

view this post on Zulip Francois Green (Jul 10 2024 at 03:55):

Thank you so much! I keep forgetting that it's commas not parentheses that connote tuple in these ML languages!

view this post on Zulip Notification Bot (Jul 10 2024 at 03:55):

Francois Green has marked this topic as resolved.


Last updated: Jul 06 2025 at 12:14 UTC