Stream: beginners

Topic: Import from platform to interface


view this post on Zulip jan kili (Sep 26 2022 at 04:11):

Can an interface import anything from the app's platform?

view this post on Zulip jan kili (Sep 26 2022 at 04:12):

I want to use interfaces as a tool for breaking up complex apps into multiple files, but that often requires referencing platform-defined types. Is this a sign that I'm misusing interfaces?

view this post on Zulip jan kili (Sep 26 2022 at 04:44):

I'm pretty sure the answer is no. :/

view this post on Zulip jan kili (Sep 26 2022 at 05:00):

Importing effects would be very nice, too... though I suppose I can always wrap interface functions in a wrapper function and pass in effects that way...

view this post on Zulip Chris Duncan (Oct 10 2022 at 20:49):

I've tried this, and it works, but there are caveats.

I'm working on the Advent of Code, and the way they structure their puzzles is that there are two daily puzzles. They share the same input, so I wrote a main.roc interface that reads, parses, and outputs the data and another mainA.roc and mainB.roc apps that did the pure puzzle-solving. Given this structure, most of my code interacting with the platform lives in main.roc.

When I run roc test mainA.roc or roc dev mainB.roc everything works well. If I run roc test or roc dev main.roc, I get errors. By running roc check by itself, I get the error that the file has an unexpected name. If I change the name according to the error, roc check runs seemingly forever.

I don't know if the expectation is to have all the code interacting with the platform in one file and only have code that solely depends on Roc's Standard Library in the interface file?

view this post on Zulip Chris Duncan (Oct 10 2022 at 20:54):

Sample code:
main.roc
mainA.roc

view this post on Zulip Lunarmagpie (Dec 22 2022 at 13:28):

Hello, I have a platform that requires a type called Model that the user specifies.
This is in a file called Platform.roc

platform "platform"
    requires { Model } { init : App.Application }
    exposes [ Model ]
    packages {}
    imports [ App ]
    provides [mainForHost]

mainForHost = init

My App.roc file needs to import the type from Platform.roc

interface App
    exposes [...]
    imports [Platform]

When I try to run this code I get an error saying that the App.roc file does not exist. I think this is because of a circular import.
Is there any way to avoid this problem?

view this post on Zulip Lunarmagpie (Dec 22 2022 at 13:30):

Seems to be the same sort of issue as the other thing in this thread but the fix doesn't seem possible, or I am misunderstanding.

view this post on Zulip Folkert de Vries (Dec 22 2022 at 13:35):

I don't think you need to import your app there

view this post on Zulip Folkert de Vries (Dec 22 2022 at 13:36):

the model type is already passed along. I think you can use { init : _ } (the underscore is a type hole, meaning the compiler will figure out that type)

view this post on Zulip Lunarmagpie (Dec 22 2022 at 13:38):

Now I don't get an error roc check is hanging.

view this post on Zulip Folkert de Vries (Dec 22 2022 at 13:39):

hmm wait. is App not your app module?

view this post on Zulip Folkert de Vries (Dec 22 2022 at 13:41):

you need some module that has a header similar to this

app "breakout"
    packages { pf: "platform/main.roc" }
    imports [pf.Game.{ Bounds, Elem, Event }]
    provides [program] { Model } to pf

program = ...

which is then used in the platform as

platform "gui"
    requires { Model } { program : _ }
    exposes [Game]
    packages {}
    imports [Game.{ Bounds, Elem, Event }]
    provides [programForHost]

view this post on Zulip Lunarmagpie (Dec 22 2022 at 13:41):

My file strucure is:

main.roc
    /platform
        /App.roc  # imports Platform
        /Platform.roc  # Named `Platform.roc` instead of `main.roc` like the examples

view this post on Zulip Folkert de Vries (Dec 22 2022 at 13:43):

I see

view this post on Zulip Lunarmagpie (Dec 22 2022 at 13:43):

Im trying to get the { Model } in the second code block from the gui example to be accessible from a different file

view this post on Zulip Folkert de Vries (Dec 22 2022 at 13:44):

to be clear: it is available in Platform.roc but you want it to be available in App.roc?

view this post on Zulip Lunarmagpie (Dec 22 2022 at 13:44):

Yes

view this post on Zulip Lunarmagpie (Dec 22 2022 at 13:45):

I want the user to import things from the App.roc file that will be typed with the Model type they are providing to me. Namely a record with a function with Model in the type signature.

view this post on Zulip Folkert de Vries (Dec 22 2022 at 13:45):

right, that does not work (today). The problem is circular dependencies. The app uses the platform, so then it would be circular if the platform could use types defined in the app. The Platform.roc module is special, because it is really the highest module. the app module (and other user modules) are in the middle, and then the other modules of the platform are below that in the hierarchy

view this post on Zulip Folkert de Vries (Dec 22 2022 at 13:46):

the workaround here is to use type variables I think

view this post on Zulip Folkert de Vries (Dec 22 2022 at 13:47):

so your App.roc would define an Application model := ..., so it is generic over whatever model the user provides

view this post on Zulip Lunarmagpie (Dec 22 2022 at 13:47):

ty for the explanation.

view this post on Zulip Lunarmagpie (Dec 22 2022 at 13:47):

thanks i think i get it

view this post on Zulip Lunarmagpie (Dec 22 2022 at 13:47):

i think

view this post on Zulip Lunarmagpie (Dec 22 2022 at 14:12):

I ended up needed to do a record like this

Application model : {
    routes : List (Route.Route model),
}

works perfectly :smile:


Last updated: Jul 05 2025 at 12:14 UTC