簡體   English   中英

Haskell自定義數據類型

[英]Haskell Custom Data Type

我正在做作業,我們有一系列混合元素Char和Int。

我創建了此自定義類型:

data Element = CharToElement Char | IntToElement Int

它將CharInt轉換為Element所以我可以處理它們。

我遇到的問題是我要轉換回去時該怎么辦?

因此,現在我做了(頭數組)並返回Element該如何將Element轉換為IntChar

這是針對后綴評估程序的。

感謝幫助。 謝謝。

編輯:

因此,我進行了處理,這就是我所擁有的:

data Element = ElementConstructor (Char, Int, Bool) | IntToElement Int | CharToElement Char | NIL

extractInt (_,i,_) = i
extractChar (c,_,_) = c
extractType (_,_,b) = b

stack_push :: [Element] -> Element -> [Element]
stack_push stack element = (element:stack)

stack_pop :: [Element] -> [Element]
stack_pop stack = (tail stack)

stack_top :: [Element] -> Element
stack_top stack = (head stack)

postfix_eval eqn = (postfix_eval_rec (postfix_eval_const eqn []) [])

postfix_eval_const eqn_raw eqn_conv =
    if null eqn_raw
        then NIL
    else
        if (isNumber (head eqn_raw))
            then ElementConstructor(NIL, (head eqn_raw), True):eqn_conv
        else if (isAlpha (head eqn_raw))
            then ElementConstructor((head eqn_raw), NIL, False):eqn_conv
        postfix_eval_const (tail eqn_raw) eqn_conv


operate :: Element -> Element -> Element -> Element
operate operator_char a b = 
    if operator_char == '+'
        then IntToElement ( (extractInt a) + (extractInt b) ) 
    else if operator_char == '-'
        then IntToElement ( (extractInt b) - (extractInt a) )
    else if operator_char == '*'
        then IntToElement ( (extractInt a) * (extractInt b) )
    else if operator_char == '/'
        then IntToElement ( (extractInt b) `div` (extractInt a) )
    else
        IntToElement(0)

postfix_eval_rec :: [Element] -> [Element] -> Int
postfix_eval_rec eqn stack = 
    if null eqn
        then (extractInt (stack_top stack))
    else if ( (extractType (head eqn)) )
        then (postfix_eval_rec (tail eqn) (stack_push stack (head eqn) ) )
    else
        (postfix_eval_rec (tail stack) (stack_push (stack_pop (stack_pop stack)) (operate (head eqn) (stack_top stack) (stack_top (stack_pop stack)))))

這個想法是,您輸入類似:postfix_eval [1,2,3,'+',4,'+','*']的結果,並且您會以Int的形式得到答案,在這種情況下,您得到9

有很多方法可以解決此問題。 我只會提供一些一般性建議。

首先,努力僅使用全部功能-永遠不會出錯的功能。 特別是,在大多數慣用的Haskell代碼中, headtail是不必要的,應將其視為代碼氣味。

此外,避免if /警衛可通過圖案匹配來代替。 您確實應該習慣了,周圍有不錯的教程

例如,這是您的operate函數的第一次重做:

operate :: Element -> Element -> Element -> Element
operate (CharToElement '+') a b =
   IntToElement (extractInt a + extractInt b) 
operate (CharToElement '-') a b =
   IntToElement (extractInt a - extractInt b) 
operate (CharToElement '*') a b =
   IntToElement (extractInt a * extractInt b) 
operate (CharToElement '/') a b =
   IntToElement (extractInt a `div` extractInt b) 
operate _                   _ _ =
   IntToElement 0

這遠非完美。 首先,為什么錯誤返回0 調用者無法將其與實際的空結果區分開。 其次,函數extractInt必定是局部的(或再次返回假結果):如果a代替char怎么辦?

最終,已經在類型級別找到了謊言:

operate :: Element -> Element -> Element -> Element

這種類型的確存在:我們並非總是對所有輸入都有結果Element 我們想對錯誤建模。 這更誠實:

operate :: Element -> Element -> Element -> Maybe Element

並且可以通過模式匹配再次實現:

operate :: Element -> Element -> Element -> Maybe Element
operate (CharToElement '+') (IntToElement a) (IntToElement b) =
   Just $ IntToElement $ a + b
operate (CharToElement '-') (IntToElement a) (IntToElement b) =
   Just $ IntToElement $ a - b
operate (CharToElement '*') (IntToElement a) (IntToElement b) =
   Just $ IntToElement $ a * b
operate (CharToElement '/') (IntToElement a) (IntToElement b) =
   Just $ IntToElement $ a `div` b
operate _                   _                _                =
   Nothing

瞧,不需要危險的extract功能。 當輸入不是整數時,由於第一個匹配失敗,我們只返回Nothing

這可能會覺得不太方便,因為現在我們需要在代碼的其余部分中處理Maybe Element ,而該代碼不再收到要使用的簡單Element 但這就是重點! 代碼的其余部分需要處理可能的錯誤,因此也必須在此處執行錯誤處理。 Maybe Element類型迫使我們這樣做。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM