Stream: beginners

Topic: Adding hosted functionality


view this post on Zulip Jared Cone (Mar 03 2022 at 20:04):

I'm trying to add hosted functionality to clear the terminal (using the CLI example as a base). I'm able to get it working by modifying Effect.roc and lib.rs, but I'm having trouble when trying to implement it in a new "Terminal" module instead. Here's my Terminal.roc:

hosted Terminal
    exposes [ clear ]
    imports [ pf.Effect, Task.{ Task } ]
    generates Terminal with []

clearTerminal : {} -> Effect.Effect {}

clear : {} -> Task {} *
clear = \{} -> Effect.map (clearTerminal {}) (\_ -> Ok {})

and here's the error I'm getting:

[nix-shell:~/roc]$ roc check /mnt/d/Home/roctest/test.roc

── TYPE MISMATCH ───────────────────────────────────────────────────────────────

Something is off with the body of the clearTerminal definition:

1│  hosted Terminal


This Terminal private tag application has the type:

    [ Terminal ({}a -> b) ]d

But the type annotation on clearTerminal says it should be:

    [ Effect.Effect ({} -> {}) ]

Tip: Seems like a tag typo. Maybe Terminal should be Effect.Effect?

Tip: Can more type annotations be added? Type annotations always help
me give more specific messages, and I think they could help a lot in
this case

────────────────────────────────────────────────────────────────────────────────

view this post on Zulip Brendan Hansknecht (Mar 04 2022 at 01:54):

Hosted is new to me (and roc in general?), but I would guess the issue is that hosted is just for effects. Instead, you probably want terminal to be more akin to the Stdout module. It wraps an effect.

view this post on Zulip Jared Cone (Mar 05 2022 at 22:59):

There aren't currently any effects for clearing the terminal, setting the cursor position in the terminal, etc. I need to add those, which requires adding some functionality in rust that can be called from roc. I can do this by modifying Effect, but I was hoping there might be a way to add another hosted module.

view this post on Zulip Brendan Hansknecht (Mar 05 2022 at 23:27):

I am pretty sure that all effects must be exposed through the effect module. They then can be imported and wrapped in other modules. So you would add an effect for clearing the terminal, but give it a nicer exposed wrapper in the terminal module.

view this post on Zulip Brendan Hansknecht (Mar 05 2022 at 23:27):

Effect is essentially the cffi specification

view this post on Zulip Ayaz Hafiz (Mar 05 2022 at 23:28):

You probably want to do

interface Terminal
    exposes [ clear ]
    imports [ pf.Effect, Task.{ Task } ]

clearTerminal : {} -> Effect.Effect {}

clear : {} -> Task {} *
clear = \{} -> Effect.map (clearTerminal {}) (\_ -> Ok {})

view this post on Zulip Ayaz Hafiz (Mar 05 2022 at 23:29):

hosted generates a new Effect implementation

view this post on Zulip Jared Cone (Mar 06 2022 at 00:54):

Is that going to allow me to implement clearTerminal in rust?

view this post on Zulip Ayaz Hafiz (Mar 06 2022 at 01:00):

I see, sorry, I misunderstood. Indeed it won't.

You could create a new hosted module that has Terminal as the effect name, but the problem is that it won't work with Task as Task is defined currently. That's because Task in the CLI platform wants the Effect type alias from the Effect module, but effects produced in the new hosted Terminal module would have to produce Terminal effects. So something like

hosted Terminal
    exposes [ clear ]
    imports [ pf.Effect, Task.{ Task } ]
    generates Terminal with [map]

clearTerminal : {} -> Terminal {}

clear : {} -> Terminal (Result {} *)
clear = \{} -> Terminal.map (clearTerminal {}) (\_ -> Ok {})

should work

view this post on Zulip Brendan Hansknecht (Mar 06 2022 at 01:58):

Why not write all the rust wrapper functions in the effect module? That is what it is made for.

view this post on Zulip Brendan Hansknecht (Mar 06 2022 at 02:00):

So Effect is the ffi module. Then Stdin, Stdout, Terminal, File, etc are the exposed modules with nice interfaces for the app to use.

view this post on Zulip Brendan Hansknecht (Mar 06 2022 at 02:01):

They just end up delegating to an effect.

view this post on Zulip Richard Feldman (Mar 06 2022 at 03:55):

@Jared Cone might be easier to pair on it - dm me if you'd like to!

view this post on Zulip Jared Cone (Mar 06 2022 at 04:28):

Will do. Yea could definitely just define everything in Effect, I was just thinking that might grow quite large if it's going to house all the functionality for terminal, filesystem, networking, etc

view this post on Zulip Yorye Nathan (Mar 07 2022 at 00:30):

if the terminal supports ANSI escape codes you can use Stdout.line to move cursor, scroll, erase, etc... Not quite a console api, but something that can be useful in the meantime :)


Last updated: Jul 05 2025 at 12:14 UTC