2017-03-08 2 views
3

F #을 배우고 있고 수레 스택에서 수학 연산을 수행해야하는 연습을하고 있습니다.중첩 연산자를 매개 변수로 보낼 때 F # 형식이 일치하지 않습니다.

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

이유 : 내가 인수로 전달하는 시도 (+, -, *, /)

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에서 컴파일러 오류를 받고 있어요 연산자는 (+)가됩니다 : float -> float -> 'a ->'b? 대화 형 콘솔에서이 유형을 복제 할 수 없었습니다. 모든 도움을 주셨습니다.

답변

4

귀하의 정의가 applyBin 인 경우 매개 변수 f(float * float) -> float 유형을 가지고 있습니다. 즉, 단일 쌍 매개 변수를 사용하고 float를 반환합니다. 응용 프로그램 f (first, second)applyBin에 있기 때문입니다. 이진 연산자 +, -, */은 모두 float -> float -> float 유형이므로 f의 형식이 applyBin 인 것으로 생각됩니다. 당신은 한 쌍의 건설을 제거하여이 작업을 수행 할 수 있습니다 : 사용자 정의 구성 운영자에 투자 할 의향이 있다면

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

트릭을 수행하는 것처럼 보였습니다. 감사! 방금 터프 팅을했다고 가정 했으므로 중개 연산자를 구현하는 방법을 배웠습니다. – Runekn

0

, 당신은 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) 

'팝'연산에서 반환되는 두 개의 인수가 여전히 있습니다. 카레 이드 인수로의 변환은 부분 적용을 가능하게하고 스택 상태를 지명 할 필요가 없습니다.