我正在實施一個使用Ocaml的模擬解釋器。其中一個模擬功能是使用模式匹配來評估組成表達式。 這個問題是微不足道的,絕對可以解決,但我試圖找到一個更優雅的方式來做到這一點,所以請繼續閱讀,如果你仍然感興趣!在Ocaml中使用try/with語句進行類型檢查?
我的用戶定義類型的代碼片段看起來是這樣的:
type value =
| Val_Int of int
| Val_Bool of bool
type expr =
| Id of string
| Int of int
| Bool of bool
| Plus of expr * expr
| Equal of expr * expr
當然,我有一個功能在(string * value) list -> expr -> value
形式評估這些表達式,函數的代碼片段看起來是這樣的:
(* Ignore this helper function if you'd like *)
let rec lookup env x = match env with
| [] -> raise (DeclarationError "Declaration Error")
| (y,v)::env_t -> if x = y then v else lookup env_t x
;;
(* The evaluation function *)
let rec eval_expr env e = match e with
| Id(x) -> lookup env x
| Int(x) -> Val_Int(x)
| Bool(x) -> Val_Bool(x)
| Plus(x,y) -> (try
let Val_Int n1 = eval_expr env x in
let Val_Int n2 = eval_expr env y in
Val_Int (n1 + n2)
with _ -> raise (TypeError "Type Error Plus"))
| Equal(x,y) -> (try
let value n1 = eval_expr env x in
let value n2 = eval_expr env y in
Val_Bool (n1 = n2)
with _ -> raise (TypeError "Type Error Equal"))
;;
這裏我使用try/with
語句來捕獲任何原生錯誤類型並拋出我自己的錯誤TypeError
。我正在使用像Val_Int n1
這樣的多態變體來保護我的變量免受無效類型操作的影響,如1 + true
,這應該會引起TypeError
。
這個問題更多的是Equals
表達式。當兩個參數是同一類型的Equals
應該只進行評估(即兩個Val_Int
或兩者Val_Bool
),如果像Equals(Val_Int(0), Val_Bool(false))
在傳遞扔TypeError
。
隨着Plus
,我可以明確地定義我的類型作爲Val_Int
,所以類似Plus(Val_Int(0), Val_Bool(false))
會引起match failure
,它會被try/with
聲明捕獲,但我不能這樣做Equals
,它可能是Val_Int
或Val_Bool
。也就是說,像Equals(Val_Int(0), Val_Bool(false))
這樣的東西只會返回Val_Bool(false)
而不是拋出一個錯誤。我能解決這個
的一種方法是,如果我用match/with
語句代替try/with
,就像如果我不喜歡的東西:
|Equal(x,y)->(match (eval_expr env x,eval_expr env y) with
|(Val_Int(a),Val_Int(b)) -> Val_Bool(a = b)
|(Val_Bool(a),Val_Bool(b)) -> Val_Bool(a = b)
|(_,_) -> raise (TypeError "TypeError Equals"))
,但我試圖找到這樣做的更優雅的方式。有什麼建議麼?
是, 「匹配」是合適的解決方案。 – Bergi
事實上,「匹配」是合適的解決方案,但他想要另一種方式。 「模擬」等同於「虛擬」嗎? – Lhooq