Search code examples
functiontypesf#argumentsmismatch

F# type mismatch when sending infix operator as parameter


I'm learning F# and is doing an exercise that requires me to perform math operations on a stack of floats.

exception InterpreterError;;
type Instruction = 
| ADD 
| SUB 
| MULT 
| DIV 
| SIN
| COS 
| LOG 
| EXP 
| PUSH of float;;

type Stack = S of float list;;

let pop (S(s)) = 
    match s with
    | [] -> raise InterpreterError
    | x::_ -> (x,S(s));;

let push x (S(s)) : Stack = S(x::s)

let applyBin f s : Stack = 
    let (first, sGen1) = pop s
    let (second,sGen2) = pop sGen1
    push (f(first,second)) sGen2;;

let applyUni f s : Stack = 
    let (first, sGen1) = pop s
    push (f(first)) sGen1;;

let intpInstr i s =
    match i with
    | ADD -> applyBin (+) s
    | SUB -> applyBin (-) s
    | MULT -> applyBin (*) s
    | DIV -> applyBin (/) s
    | SIN -> applyUni sin s
    | COS -> applyUni cos s
    | LOG -> applyUni log s
    | EXP -> applyUni exp s
    | PUSH(r) -> push r s;;

However, I'm getting a compiler error in the last function intpInstr on the infix operators (+, -, *, /) that I try to pass as arguments:

Type mismatch. Expecting a
    float * float -> float    
but given a
    float * float -> 'a -> 'b    
The type 'float' does not match the type ''a -> 'b'

Why does the operators become (+) : float -> float -> 'a -> 'b? I haven't been able to replicate this type in the interactive console. All help appreciated.


Solution

  • With your definition of applyBin the parameter f has type (float * float) -> float i.e. it takes a single pair parameter and returns a float. This is due to the application f (first, second) in applyBin. The binary operators +, -, * and / all have type float -> float -> float so it looks like you intend that to be the type of f within applyBin. You can do this by removing the pair construction:

    let applyBin f s : Stack = 
        let (first, sGen1) = pop s
        let (second,sGen2) = pop sGen1
        push (f first second) sGen2