top | item 21446268

(no title)

lacampbell | 6 years ago

Haven't had a coffee yet so go easy on me - doesn't this solve your issue?

    interface Functor<A> {
        map<B>(f: (a: A) => A): Functor<A>;
    }
You map over an option, you get an option. You map over an either, you get an either. etc etc.

discuss

order

tel|6 years ago

That gets closer to the problem, but the solution is further away. You don't want to return "Functor" (which is like a vtable, the interface itself) but instead the thing itself which is implementing the Functor interface.

So you end up with

    interface Functor<A> {
        map<B>(f: (a: A) => A): Self<B>
    }
where `Self` needs to recognize that the type being defined to implement this interface has a "slot". This tends to make things tough.

rubyn00bie|6 years ago

I'd like to +1 that "tends to make things tough." Not sure how it is today, I think it was remedied in Swift 4.1 or something... but holy-shit, that "slot" problem gave me endless grief trying to implement functors in swift for composing UI structs (I was ahead of the curve, heh).

lacampbell|6 years ago

You've lost me. Returning an interface isn't returning a concrete thing. It's returning the thing that implements the interface

I'm a very low level functional programmer. I'm big on immutability, big on not using loops and instead using map/flatMap/filter/fold, I tend to roll my own either and option implementations when they don't exist because it's the tidiest way of handling errors I've come across, etc etc. But when it comes to stuff like functors I don't get what it's buying me. What interesting stuff can I do if I know that both an option and a list can be mapped over?

I really need to look more deeply into it at some stage. I might be missing out on some powerful tools. Or it might be a bunch of stuff that's theoretically interesting but practically useless.

smegma2|6 years ago

The functor it returns should be the same functor it was called on, i.e. calling map on a Maybe should return a Maybe. The parameterized type can change so map can bring you from a Maybe<Int> to a Maybe<String> which is why in the above description we have Functor<B> instead of A. But what typescript is lacking is a way to describe that the functor returned should be the same.