1

試圖動態評價習慣F#我試過小例子,我的下一步就是寫幾個函數邏輯運算/評估,現在我有這個結構F#類型和基本的計算

type Expr = 
    | True 
    | False 
    | Not of Expr 
    | And of Expr * Expr 

它應該是顯而易見的,我想實現的目的是:能夠封裝不同的功能,如NotAnd用於像And(And(True, Not(False)), True)這樣的計算,但目前我不明白(這是我第一次打這樣的「複雜」功能代碼)如何使用這個結構並編寫適當的方法,例如我可以寫評估

let evalLogic (expr : Expr) : bool = 
    match expr with 
    | True -> true 
    | False -> false 
    | _  -> false (* eval the expression which is not "atomic" *) 

,然後作爲一種方法

let And (left : Expr , right : Expr) : Expr = 
    let value = evalLogic(left) && evalLogic(right) 
    match value with 
    | true -> True 
    | false -> False 

但我知道,這是廢話,不執行此正確的方式!你能否給我一個提示,告訴我如何達到預期的行爲,並描述如何擴展它?

回答

6

當編寫功能代碼來表示和計算表達式的典型模式是定義表達式的類型爲區分聯合(就像你一樣!),然後編寫一個接受表達式並返回結果的函數。你的邏輯表達式將評估爲布爾值,因此你需要一個函數:

evalLogic : Expr -> bool 

在功能,你需要編寫每一個可能的表達情況。您的示例處理FalseTrue,Bluepixy的代碼顯示了其餘部分。一般的想法是函數可以遞歸地評估所有子表達式 - 如果有And(e1, e2),則可以將e1e2評估爲兩個布爾值,然後將它們組合(使用&&)。

您的And函數不是必需的,因爲整個評估都在evalLogic函數中完成。這是在功能風格中做事的典型方式(因爲表達式類型不會經常變化)。 Howeever,你也可以使用支持更多的二進制運算:

type Expr = 
    | Constant of bool 
    | Unary of Expr * (bool -> bool) 
    | Binary of Expr * Expr * (bool -> bool -> bool) 

這裏,這個想法是一個表達式是常數或一些二進制或一元邏輯運算器的應用。例如,爲了表示true && not false,你可以寫:

Binary(Constant(true), Unary(Constant(false), not), (&&)) 

現在表達式樹還攜帶了要使用的功能,所以評價只需要調用的函數(你可以很容易地使用所有標準的邏輯運算符)。例如,對於Binary的情況是這樣的:

let rec evalLogic e = 
    // pattern matching 
    | Binary(e1, e2, op) -> op (evalLogic e1) (evalLogic e2) 
+0

+1我覺得函數式編碼在開始的時候非常怪異而且非常痛苦,因爲我編寫C++和C#已經有半年了,但是你的解釋很棒,F#對我來說越來越有趣了;-) - Can你進一步解釋我,是否有可能** NOT **來評估'Constant'直到真正需要,例如我正在使用'True'和'False',並且只在執行像'evalConst(e:Constant)'這樣的東西時才被評估。 –

2

是你的問題「我如何將evalLogic延伸爲NotAnd?」

如果是這樣,那麼你需要在鬆懈的表達擴展模式匹配其他兩個構造函數匹配:

let evalLogic (expr : Expr) : bool = 
    match expr with 
    | True -> true 
    | False -> false 
    | Not (myexpr) -> ... (* match constructor `Not`, bind the expression to `myexpr`) 
    | And (lefte, righte) -> ... 

然後你可以在一些F#代碼右手邊補。

Here's有關F#中模式匹配的一些信息。

3
let rec evalLogic (expr : Expr) : bool = 
    match expr with 
    | True -> true 
    | False -> false 
    | Not (exp) -> not (evalLogic exp) 
    | And (expL, expR) -> evalLogic expL && evalLogic expR 

DEMO

> evalLogic <| And(And(True, Not(False)), True);; 
val it : bool = true 
+0

這整個事情是我在F#的研究,因爲我想寫小CAS組件(有人告訴我嘗試函數式編程語言),我想知道,如何例如,如果我想實現100個功能,我可以構建一個更好的結構。在這種情況下,一個非常大的匹配模式將會過度,呃? –

+0

如果您誤解了您不確定的含義,我很抱歉。 如果你正在考慮一些數據結構100個模式,那麼它可能會拆分函數來拆分結構。 – BLUEPIXY