2014-01-16 41 views
2

我想格式化這個功能:格式化長模式匹配

getEnv :: [Func] -> ([Char] -> RetType) 
getEnv [] = (\_ -> undefined) 
getEnv ((Func (RetTypeType t) (Ident fname) _ _):fs) = (\x -> if x == fname then t else getEnv fs) 

問題是由長模式匹配造成的,現在我不想改變構造函數的名稱。另外第三行功能的右側部分對我來說也不容易格式化。

雖然不是生死攸關的問題,但我很好奇你如何格式化這段代碼。謝謝。

回答

6

基本上,你有兩種可能性:

事情是這樣的:

getEnv ((Func 
      (RetTypeType t) 
      (Ident fname) _ _) 
     :fs) 
    = (\x -> if x == fname then t else getEnv fs) 

,或者您可以使用模式衛士:

getEnv (h:fs) 
    | Func a b _ _ <- h, 
    Rectype t <- a, 
    Ident fname <- b 
    = (\x -> if x == fname then t else getEnv fs) 

你可以進一步避免拉姆達:

getEnv (h:fs) x 
    | Func a b _ _ <- h, 
    Rectype t <- a, 
    Ident fname <- b 
    = if x == fname then t else getEnv fs 

「開放」模式守衛的缺點可能是編譯器無法再決定你的模式是否詳盡無遺。

由於@leftaroundabout所指出的,我們可以把它更加明確地這樣:

getEnv (h:fs) x 
    | Func a b _ _ <- h, 
    Rectype t <- a, 
    Ident fname <- b, 
    x == fname   = t 
    | otherwise   = getEnv fs 

這也將讓編譯器知道該列表的頭部的所有可能的形式都包括在內,所以這個我」 d術語是實現它的最佳方式。

+0

當你已經在模式守衛,爲什麼不在那裏包括'x == fname'條件?它非常適合。 - 另一方面,我更喜歡把逗號放在一開始,與'|'一致,就像Haskell中相當常見的樣式一樣(當然,這是一個有趣的事情)。 – leftaroundabout

+0

@leftaroundabout看到,當行以逗號開始時,我可能會討厭它。除此之外。我將編輯我的帖子以顯示'x == fname' – Ingo

+0

Exaustive答案,我選擇最後的樣式,謝謝! – optimusfrenk

2

我通常會簡單地做

getEnv :: [Func] -> ([Char] -> RetType) 
getEnv [] = (\_ -> undefined) 

getEnv ((Func (RetTypeType t) (Ident fname) _ _):fs) 
      = \x -> if x == fname then t else getEnv fs 

但是我想,如果我是做了很多的使用記錄語法

data Func = Func {returnTypeType :: RetTypeType, 
        identifier :: Ident, 
        .... } 
data RetTypeType = RetTypeType {unRetTypeType :: RetType} 
data Ident = Ident {unIdent:: String} 

傾斜,這樣我就可以寫

getEnv :: [Func] -> ([Char] -> RetType) 
getEnv [] = (\_ -> undefined) 
getEnv (f:fs) = \x -> if x == ident f 
         then unRetTypeType.returnTypeType $ f 
         else getEnv fs 
0

首先,我嘗試保持模式si mple。通常它只是一個帶變量或下劃線的構造函數,因爲它是參數。異常:像(:)或(,)這樣的內置構造函數不計數。所以,如果你有這種模式匹配,我認爲你做錯了什麼。其次,我只是將'='分開並且很高興。