2013-10-06 67 views
2

我是初學者,我使用的術語可能不準確。OCaml:使用匹配和類型鑄造

type t = True | False | If of t * t * t | Int of int | Plus of t * t | GT of t * t 

let isval t = 
    match t with 
     True|False -> true 
    | Int _ -> true 
    | _ -> false 

我想實現一個eval函數。

let rec step t = 
    match isval t with 
     true -> raise NormalForm 
    | false -> match t with 
      If(t1, t2, t3) when t1=True -> t2 
     | If(t1, t2, t3) when t1=False -> t3 
     | Plus(t1, t2) -> t1+t2 
     | GT(t1, t2) -> t1>t2 
     | _ -> raise NormalForm;; 

錯誤發生在Plus(t1, t2) -> t1+t2,稱「這個表達式的類型爲t,但預計int類型的表達」。

什麼問題?我應該如何解決它?

回答

1

match表達式(不幸)沒有結束標記。對於嵌套的match,您必須使用括號或begin ... end代碼

match x with 
    SomePattern y -> begin 
    match y with 
     AnyotherThing -> .... 
     YetAnotherPattern z -> .... 
    end 

,你有一個類型的問題:做t1+t2當你step功能是給一個int,做t1>t2當是給bool;這是不可能的,一個函數應該返回一些已知(單一)類型。

您可能需要定義

type result_t = NoResult | IntResult of int | BoolResult of bool 

,並給IntResult (t1+t2)BoolResult (t1>t2)

,或者你可以簡單地step返回一些t值,即TrueFalseInt (t1+t2)

我反而代碼

let asint = function Int x -> x | _ -> failwith "not an integer" 

let rec eval = function 
    True -> True 
    | False -> False 
    | Int x -> Int x 
    | If (cond,thenpart,elsepart) -> begin 
     match eval cond with 
     True -> eval thenpart 
     | False -> eval elsepart 
     | _ -> failwith "bad condition" 
    end 
    | Plus (l, r) -> 
     Int (asint (eval l) + asint (eval r)) 
    | GT (l, r) -> begin 
     if (asint (eval l)) > (asint (eval r)) then 
     True 
     else 
     False 
    end 
3

由於編譯器說+運算符在整數。但是你將它應用於t類型的子表達式。由於您的t類型可以代表Plus(True, False)之類的內容,因此您需要決定實際上您是如何處理這些情況的。

您還需要決定返回類型。您的一些案例似乎正在返回bool,其他人返回t,其他人返回int。從外觀上看,你可能想在所有情況下返回t。如果是這樣,您將返回Int n,而不僅僅是簡單的n

(Basile Starynkevitch編寫了一些解決這些問題的代碼,也許先考慮一下他們,然後看看他的代碼:-)