Stream: beginners

Topic: Purity Inference and Testing


view this post on Zulip Unshipped9094 (Jan 28 2025 at 03:35):

Heard recently that there's a new plan for how Roc will be handling effects, essentially moving away from Tasks entirely.

One of the best things IMO about haivng a concrete type to represent "an effect that will be executed by the runtime" is that it makes testing so much easier. Instead of having to set up mocks, or do some complicated dependency injection, you can just assert that your code returns a certain kind of task with the payload that you expect. Testing the code that handles this result is usually really easy too, because you can just pass in some data that you expect the runtime to give you back.

When you have code that can call an effect anywhere inside, it becomes much harder to test (even if you have the guarantees from the type checker about pure functions vs effectful functions). If you can directly call an effect, now it's up to the author to minimize the other code surrounding the effect. For example, if you have a function that transforms its arguments in some way, then calls some effect, and then transforms the result in some way, this is much harder to test.

I'm curious what the thoughts are here - is this something that's considered? Am I just misunderstanding the way this will work?

view this post on Zulip Brendan Hansknecht (Jan 28 2025 at 03:39):

Tasks where not reasonably testable before, so I don't think this makes much of a difference on that front. Unlike elm where you return a message that is easily concrete for testing, tasks have never been that way. So I don't think we lost anything there

view this post on Zulip Brendan Hansknecht (Jan 28 2025 at 03:40):

I do agree that it still leaves a hole around testing. A number ideas exist for making that nice, but nothing implemented currently.

view this post on Zulip Sam Mohr (Jan 28 2025 at 03:58):

I'd say the only difference between Tasks and effectful functions is laziness. They literally compile to the same thing, except one is \{} -> run effect and the other is run! effect.

view this post on Zulip Sam Mohr (Jan 28 2025 at 04:03):

So any problems with one apply to the other, except for all the lambda set bugs we've avoided by not using a bunch of thunks.

view this post on Zulip Unshipped9094 (Jan 28 2025 at 04:46):

Yeah I guess I'm mainly comparing it to Elm, where you would just really test your main update function with some inputs and assert that the return value is the state you expect and the effect you expect to run, as well as your update function with the next state and result of the previous Cmd.

view this post on Zulip Kilian Vounckx (Jan 28 2025 at 05:52):

Effects are still tracked though. If a function has an effect, it has a different type to a function which doesn't. And a function which doesn't have effects cannot call a function which does (kind of like async in other languages). So you always know when effects happen. And you are encouraged to minimize effect usage

view this post on Zulip Brendan Hansknecht (Jan 28 2025 at 06:27):

the same as elm could be done in roc, but it would be very limiting. You would make a platform that takes a union of commands as output. So it would have no effects. Everything would go through that one tag. It would actually be 100% pure. Would make it a lot more directly testable like in elm.

view this post on Zulip Anthony Bullard (Jan 28 2025 at 11:04):

This is basically the exact design of the platform I hope to build once I have time. The language I designed and was trying to build before I came to Roc was basically Roc with Actors, managed effect runtime, and less sugar and no ad hoc polymorphism.

So building a platform that just defines a Cmd tag union and expects a function that returns an Actor type (maybe tag union as well) would allow me to test building apps using the same basic design.

view this post on Zulip Anton (Jan 28 2025 at 11:06):

I love actors :) Did you use akka in the past as well?

view this post on Zulip Anthony Bullard (Jan 28 2025 at 11:07):

I had contact with Akka, I think I only really helped on one ETL system that used it when I was at a Scala shop for 4 years.

view this post on Zulip Anthony Bullard (Jan 28 2025 at 11:07):

But I really nerded out on Elixir/Erlang for awhile after learning about the concept

view this post on Zulip Anthony Bullard (Jan 28 2025 at 11:08):

And in late 2018/early 2019 I even tried to contribute to Pony (a very performant, but very complicated Actor-oriented language)

view this post on Zulip Anthony Bullard (Jan 28 2025 at 11:10):

Combine that with a love of Elm, and you get Chakra (my language)

view this post on Zulip Anthony Bullard (Jan 28 2025 at 11:10):

But Chakra will probably never be now that there is Roc.

view this post on Zulip Unshipped9094 (Jan 29 2025 at 01:32):

Kilian Vounckx said:

Effects are still tracked though. If a function has an effect, it has a different type to a function which doesn't. And a function which doesn't have effects cannot call a function which does (kind of like async in other languages). So you always know when effects happen. And you are encouraged to minimize effect usage

Yup, I watched the the Functional Purity Inference Plan talk, so I'm aware of the plan with A => B vs A -> B. I imagine the feel will be similar to Haskell, where you try to minimize the code that needs to be in any kind of IO code.

view this post on Zulip Unshipped9094 (Jan 29 2025 at 01:34):

Brendan Hansknecht said:

the same as elm could be done in roc, but it would be very limiting. You would make a platform that takes a union of commands as output. So it would have no effects. Everything would go through that one tag. It would actually be 100% pure. Would make it a lot more directly testable like in elm.

Basically making a platform that's using the Elm Architechture? That might be limited but I can see it being great for things like command line apps.

view this post on Zulip Brendan Hansknecht (Jan 29 2025 at 01:45):

Yeah, definitely can have its uses. TEA can be amazing when designed well for a domain


Last updated: Jul 05 2025 at 12:14 UTC