发送中缀运算符作为参数时 F# 类型不匹配
F# type mismatch when sending infix operator as parameter
我正在学习 F#,并且正在做一个练习,要求我对一堆浮点数执行数学运算。
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;;
但是,我在尝试作为参数传递的中缀运算符(+、-、*、/)上的最后一个函数 intpInstr 中遇到编译器错误:
Type mismatch. Expecting a
float * float -> float
but given a
float * float -> 'a -> 'b
The type 'float' does not match the type ''a -> 'b'
为什么运算符会变成 (+) : float -> float -> 'a -> 'b?我无法在交互式控制台中复制这种类型。
感谢所有帮助。
根据您对 applyBin
的定义,参数 f
的类型为 (float * float) -> float
即它采用一对参数和 returns 一个浮点数。这是由于 applyBin
中的应用程序 f (first, second)
。二元运算符 +
、-
、*
和 /
都具有类型 float -> float -> float
因此看起来您打算将其作为 [=12= 的类型] 在 applyBin
内。您可以通过删除对结构来做到这一点:
let applyBin f s : Stack =
let (first, sGen1) = pop s
let (second,sGen2) = pop sGen1
push (f first second) sGen2
如果你愿意投资于自定义组合运算符,你可以使用eta reduction并更简洁地表达函数应用的逻辑。
let (>|>) f g = f >> fun (b, c) -> g b c
let applyUna f =
pop >|> fun first ->
push (f first)
let applyBin f =
pop >|> fun first ->
pop >|> fun second ->
push (f first second)
'pop' 操作仍然返回两个元组参数。它们转换为 curried 参数可以实现部分应用并避免命名任何堆栈状态的需要。
我正在学习 F#,并且正在做一个练习,要求我对一堆浮点数执行数学运算。
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;;
但是,我在尝试作为参数传递的中缀运算符(+、-、*、/)上的最后一个函数 intpInstr 中遇到编译器错误:
Type mismatch. Expecting a
float * float -> float
but given a
float * float -> 'a -> 'b
The type 'float' does not match the type ''a -> 'b'
为什么运算符会变成 (+) : float -> float -> 'a -> 'b?我无法在交互式控制台中复制这种类型。 感谢所有帮助。
根据您对 applyBin
的定义,参数 f
的类型为 (float * float) -> float
即它采用一对参数和 returns 一个浮点数。这是由于 applyBin
中的应用程序 f (first, second)
。二元运算符 +
、-
、*
和 /
都具有类型 float -> float -> float
因此看起来您打算将其作为 [=12= 的类型] 在 applyBin
内。您可以通过删除对结构来做到这一点:
let applyBin f s : Stack =
let (first, sGen1) = pop s
let (second,sGen2) = pop sGen1
push (f first second) sGen2
如果你愿意投资于自定义组合运算符,你可以使用eta reduction并更简洁地表达函数应用的逻辑。
let (>|>) f g = f >> fun (b, c) -> g b c
let applyUna f =
pop >|> fun first ->
push (f first)
let applyBin f =
pop >|> fun first ->
pop >|> fun second ->
push (f first second)
'pop' 操作仍然返回两个元组参数。它们转换为 curried 参数可以实现部分应用并避免命名任何堆栈状态的需要。