简体   繁体   中英

Define several members dynamically in class/interface using F#

I'm working on small program using F# just for the personal training and got some moment, which I can't solve.

I'm describing some interface:

type IСalculations =
    abstract member Add : int * int -> int
    abstract member Subtract : int * int -> int
    abstract member Multiply : int * int -> int
    abstract member Divide : int * int -> int

As you can see, the member signature besides the name is the same.

Am I able to do using F# the next (now will be pseudo-code ):

let names = [ "Add", "Subtract", "Multiply", "Divide" ];
let ICalculations = new interface;

foreach ( name in names ) {
    ICalculations[ name ] : int * int -> int
}

The aim is NOT to repeat for each member the signature int * int -> int

Is it possible?

You cannot define interface method types after the interface declaration. But you can define for example Dictionary, containing functions of your type:

open System.Collections.Generic    
type Ops = Add | Subtract | Multiply | Divide
let pseudoInterface = Dictionary<Ops, int * int -> int>()

// Then somewhere in your program you could define this "methods"
pseudoInterface.[Add] <- fun (i, j) -> i + j
pseudoInterface.[Subtract] <- fun (i, j) -> i - j // etc...

Or you can define type alias for function type for brevity:

type Op = int * int -> int
type IСalculations =
    abstract member Add : Op    
    abstract member Subtract : Op
    abstract member Multiply : Op
    abstract member Divide : Op

The only syntax for declaring an interface is :

// Interface declaration:
[ attributes ]
type interface-name =
   [ interface ]     [ inherit base-interface-name ...]
     abstract member1 : [ argument-types1 -> ] return-type1
     abstract member2 : [ argument-types2 -> ] return-type2
     ...
   [ end ]

In the second line of your pseudo-code :

let ICalculations = new interface;

you wish to use a let binding or equivalent. Unfortunately, let bindings only associate an identifier with a value or a function and not with a type or an interface. So I am afraid there is no way. Other functional languages than F#, such as Idris, can do it. If you are only bothered by the verbosity of having to repeat int*int->int, you can define a type alias like so :

module T =
  type Op = int * int -> int

type IСalculations =
    abstract member Add : T.Op
    abstract member Subtract : T.Op
    abstract member Multiply : T.Op
    abstract member Divide : T.Op

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM