2016-09-29 67 views
1

beginner f#程序員在這裏。F#返回大小的輸入定義爲構造函數

所以基本上我完全失去了。在過去的一個小時裏,我一直盯着這個問題,甚至不知道如何設置let參數的第一行。這個問題是要求使用模式匹配定義遞歸函數尺寸:EXPR - > int值返回其輸入表達式的denfied從類型EXPR構造的在表達

這是遞歸函數的數量的大小:

size : expr -> int 

下面是構造函數:

type oper = Neg | Not | Add | Mul | Sub | Less | Eq | And 

type expr = 
    | C of int 
    | Op1 of oper * expr 
    | Op2 of oper * expr * expr 
    | If of expr * expr * expr 

例如,

size(C 4) 

將返回1

size (IF (C 4, Op2 (Add, C 1, C 2), C()) 

將返回6

修訂建議後提出:進行中!

let rec size (e : expr) : int = 
    match e with 
    | C i -> 1 
    | Op1 (o, e1) -> size e1 + 1 
    | Op2 (o, e1, e2)-> size e2 + 1 
    | If (e1, e2, e3) -> size e3 + 1 
+1

刪除約0應該是你想要什麼 –

+1

功能類型是位'EXPR - > int',這意味着它應該採取一個* *參數類型的'expr',並返回一個' int'。到目前爲止,您已經定義了一個函數,它需要*兩個*參數,一個'expr'和一個'oper'。你實際上並不需要第二個參數。 'expr'類型攜帶運算符作爲數據;如果你有'expr',你可以通過使用匹配模式來獲取其中的任何'操作符'值。即'用this匹配此表達式Op1(o,e) - > ...'現在你有一個變量'o',它是'thisExpr'中的'oper'。 – rmunn

+1

一旦你開始寫你的功能,還有一個提示。當編寫像'size'這樣的遞歸函數時,有時候可能會卡住「好吧,我需要在這裏調用我的'size'函數...但是由於我還沒有寫出它,我怎麼知道它將會怎樣返回?」最好的解決方法是**假裝你已經編寫了函數**,所以你已經知道它將返回什麼 - 然後使用該函數。也就是說,如果你有一個'Op1',你知道它的大小是它所包含的'expr'的大小,再加上1.你可以告訴它它的大小嗎?您正在編寫的'size'函數! – rmunn

回答

2

我來總結一下,你是在評論中給出的提示,讓別人誰發現這個問題可以看出,這是回答你能解決這個問題:

  1. 您的原始代碼不需要oper類型的參數; expr類型的單個參數就足夠了。
  2. 你不需要一個可變的計數器變量;遞歸將更好地爲您服務。

  3. 當寫像size一個遞歸函數,有時你可以停留在「好了,我要在這裏叫我size功能......但因爲我沒有寫它,我怎麼知道是什麼回事回來?」最好的辦法是假裝你已經編寫了功能已經,所以你已經知道它會返回什麼 - 然後使用該功能。神奇的是,這一切都奏效了:當你完成這個功能時,它所調用的函數(本身)也完成了!有趣的是如何解決。 :-)

  4. 在一個點上,你有一個看起來像這樣的功能:這是給你一個StackOverflowException

    let rec size (e : expr) : int = 
        match e with 
        | C i -> 1 
        | Op1 (o, e1) -> size e + 1 
        // Rest of function omitted 
    

    ,因爲調用size eOp1比賽機箱內部是一個無限遞歸循環。提示:在心理上追蹤那個呼喚,並思考它會經歷的步驟。它將檢查eOp1,並且第二次致電size e。該電話將檢查eOp1,並且第三次致電size e。那會終止嗎?這些調用每個都會做與以前的調用不同的任何事情嗎?或者他們會一直「循環」循環,直到函數堆棧空間不足?

  5. 最後,如果您有兩個或三個expr變量,您需要處理所有這些變量,而不僅僅是一個。