Where has Functor disappeared from Arrow? In 0.12 ...

# arrowv

Ville Peurala

09/21/2022, 6:44 AMWhere has Functor disappeared from Arrow? In 0.12 it was there: https://arrow-kt.io/docs/0.12/arrow/typeclasses/functor/
How do I implement a Functor for my own type in 1.1.3?

s

simon.vergauwen

09/21/2022, 6:55 AMHey **@Ville Peurala**,
It was deprecated in 0.12.x, and removed in 0.13.x. Functor (& co) was a abstraction that didn't work well in Kotlin, we tried to look for many solutions and alternatives and we ended removing it in favor of the monadic suspend DSL system we have now.
Not sure if you've been able to take a deep look at it? We introduced the first version in 0.13.x, refining it in 1.x.x and I think we've nailed it for Arrow 2.x.x which we're actively working on now.

v

Ville Peurala

09/21/2022, 6:56 AMThanks for the info **@simon.vergauwen**. Can you give me a link to some up-to-date documentation about the monadic suspend DSL system?

s

simon.vergauwen

09/21/2022, 6:57 AMHere is the PR with the design document for Arrow 2.x.x, https://github.com/arrow-kt/arrow/pull/2797
And in similar fashion how we design *unwrapped monadic DSLs* for a different monad Resource, also known as Managed. https://github.com/arrow-kt/arrow/pull/2786
The current 1.x.x documentation can be found here, https://arrow-kt.io/docs/apidocs/arrow-core/arrow.core.continuations/-effect/

simon.vergauwen

09/21/2022, 6:57 AMNot sure if that solves your current problem, but I'd be happy to take a closer look at your use-case if you could provide some more details or code 🙂

v

Ville Peurala

09/21/2022, 7:01 AMThanks a lot! I can provide some details.
I have an interface `Timed<A>`:

```interface Timed<A> {

fun result(): A

fun startMs(): Long

fun endMs(): Long

}```Now I would like to make

`Timed`

a Functor so that users could always map overt the result without affecting the timings.Ville Peurala

09/21/2022, 7:03 AMI could just add a function

`fun <B> map(fn: (A) -> B): Timed<B>`

to my interface but I have the feeling that it is not an optimal solution.s

simon.vergauwen

09/21/2022, 7:04 AMThis is mostly oriented around *monadic DSLs* so that implies *traverse* 🎉
So in this case I would opt for adding *zip* or

`bind`

or `flatMap`

. Since in Kotlin we don't have a need for `Functor`

for collections.
I.e. you can do `list.map { either.bind() }`

safely within a DSL to replace `map`

, or I think you would need to define `Applicative`

as well and then you can also implement `Monad`

.simon.vergauwen

09/21/2022, 7:05 AMThe problem for *zip* is how do you combine

`startMs`

and `endMs`

does it take the earliest `startMs`

and the latest `endMs`

? 🤔simon.vergauwen

09/21/2022, 7:05 AMIf these are questions that don't make sense for your use-case I would opt for simply adding the

`map`

function.simon.vergauwen

09/21/2022, 7:06 AMTip: if you implement it as

`inline`

you will be able to call `suspend`

functions from the lambda, but you'll need to write `map`

as an extension function on `Timed<A>`

since `inline`

functions need to be `final`

😉v

Ville Peurala

09/21/2022, 7:07 AMThanks for the ideas. Yeah, the definition of an Applicative for

`Timed<A>`

would need some thinking about, but I'm not sure yet whether I need it. I might need a Monad too, but I'll start with a Functor now and see where that takes me.s

simon.vergauwen

09/21/2022, 7:17 AMI quickly whipped something up quickly.

simon.vergauwen

09/21/2022, 7:18 AM`timed { transform(timedA.bind(), timedB.bind(), timedC.bind(), ...) }`

and the strategy it applies over combining `startMs`

and `endMs`

is parameterised.simon.vergauwen

09/21/2022, 7:19 AMv

Ville Peurala

09/21/2022, 7:20 AMWow! You wrote my code for me! Thanks. 😄 👍

10 Views