ts2fable icon indicating copy to clipboard operation
ts2fable copied to clipboard

avoid member overloads

Open ctaggart opened this issue 8 years ago • 5 comments

It would be nice to avoid overloads. While working on http://blog.ctaggart.com/2017/11/how-to-create-http2-app-in-f.html, it was a major pain to get the F# compiler to use the correct unique overload, especially with optional parameters and base classes that have identical signatures.

image

That is from server.listen 8843..

I had issues withe end as well:

  type [<AllowNullLiteral>] ServerHttp2Stream =
        inherit Http2Stream

    type [<AllowNullLiteral>] Http2Stream =
        inherit stream.Duplex

        abstract ``end``: unit -> unit
        abstract ``end``: chunk: obj * ?cb: Function -> unit
        abstract ``end``: chunk: obj * ?encoding: string * ?cb: Function -> unit

    type [<AllowNullLiteral>] stream.Writable =
        abstract ``end``: unit -> unit
        abstract ``end``: chunk: obj * ?cb: Function -> unit
        abstract ``end``: chunk: obj * ?encoding: string * ?cb: Function -> unit

ctaggart avatar Nov 22 '17 20:11 ctaggart

I was facing the same problem when working with Fable + Express.

My way around it and to propose a better DSL was to use static constraints there can be tedious to write probably.

Express sugar synthax You can see the resulting DSL here. Don't know if this can be useful or no.

MangelMaxime avatar Nov 22 '17 20:11 MangelMaxime

Thinking out loud here. How do we solve this case:

    type [<AllowNullLiteral>] Http2SecureServer =
        inherit tls.Server

    type [<AllowNullLiteral>] Server =
        inherit net.Server

    type [<AllowNullLiteral>] Server =
        inherit events.EventEmitter
        abstract listen: ?port: float * ?hostname: string * ?backlog: float * ?listeningListener: Function -> Server
        abstract listen: ?port: float * ?hostname: string * ?listeningListener: Function -> Server
        abstract listen: ?port: float * ?backlog: float * ?listeningListener: Function -> Server
        abstract listen: ?port: float * ?listeningListener: Function -> Server
        abstract listen: path: string * ?backlog: float * ?listeningListener: Function -> Server
        abstract listen: path: string * ?listeningListener: Function -> Server
        abstract listen: options: ListenOptions * ?listeningListener: Function -> Server
        abstract listen: handle: obj * ?backlog: float * ?listeningListener: Function -> Server
        abstract listen: handle: obj * ?listeningListener: Function -> Server

May be something like parameter count and the number of times the parameter count showed up if more than one. The suffix only shows up on overloads.

    type [<AllowNullLiteral>] Server =
        inherit events.EventEmitter
        abstract listen: ?port: float * ?hostname: string * ?backlog: float * ?listeningListener: Function -> Server
        abstract listenP3: ?port: float * ?hostname: string * ?listeningListener: Function -> Server
        abstract listenP3N2: ?port: float * ?backlog: float * ?listeningListener: Function -> Server
        abstract listenP2: ?port: float * ?listeningListener: Function -> Server
        abstract listenP3N3: path: string * ?backlog: float * ?listeningListener: Function -> Server
        abstract listenP2N2: path: string * ?listeningListener: Function -> Server
        abstract listenP2N3: options: ListenOptions * ?listeningListener: Function -> Server
        abstract listenP3N4: handle: obj * ?backlog: float * ?listeningListener: Function -> Server
        abstract listenP2N4: handle: obj * ?listeningListener: Function -> Server

Good/bad/something better?

ctaggart avatar Nov 22 '17 21:11 ctaggart

Seems a little strange/hard to read.

But it's a good idea to let the classic listen with the derivated methods

MangelMaxime avatar Nov 22 '17 21:11 MangelMaxime

As a counterpoint to this issue, I think method overloads are doable if we avoid obj type and had return types that were tied to specific options. See here for more info

jgrund avatar Nov 22 '17 23:11 jgrund

Yes, overloads are complicated in F#, that was one of the reasons to create the erased unions instead of automatically generating overloads.

I cannot think of a solution now. If adding a suffix I would like something more meaningful than just the number of parameters, but I know this is hard to with an automatic processor. @jgrund is right in that filling some objs would help the compiler. I've also seen sometimes that removing optional arguments solves the ambiguity (see this commit), maybe we could try to implement an algorithm to see when can this be done.

alfonsogarciacaro avatar Nov 23 '17 20:11 alfonsogarciacaro