簡體   English   中英

Haskell 中的嵌套“where”或“let in”CodeStyle

[英]Nested "where" or "let in" CodeStyle in Haskell

我在 Haskell 中遇到了一些問題:代碼風格和大功能(我通過編寫玩具語言繼續學習 Haskell)。

我有一些必要的大功能(參見示例)。 其中有兩個子功能(嵌套在哪里)。 並且沒有理由將其子功能放在模塊 scope 中。 “Haskell 代碼風格”或“Haskell 代碼風格最佳實踐”如何建議解決“不優雅和笨拙的代碼”問題?

Function(后面有評論):

-- We can delete (on DCE) any useless opers.
-- Useful opers - only opers, whitch determine (directly or transitivery) result of GlobalUse oper
addGlobalUsageStop :: [Var] -> IR -> IR
addGlobalUsageStop guses iR = set iOpers (ios ++ ios') $ set opN opn' iR
    where
    ios = _iOpers iR
    gdefs = _gDefs iR :: M.Map Int Var
    opn = _opN iR
    guses' = nub $ filter isRegGlobal guses
    ogs = catMaybes $ map (concatIOperWithGDef gdefs) $ reverse ios
        where
        concatIOperWithGDef gdefs' (i, o) = case gdefs' M.!? i of
            Nothing -> Nothing
            Just gd -> Just (o, gd)
    nops = newGUses ogs guses'
        where
        newGUses [] _ = []
        newGUses _ [] = []
        newGUses ((Oper _ d _ _, g):os) guses = if elem g guses
            then (Oper GlobalUse g (RVar d) None):newGUses os (filter (g /=) guses)
            else newGUses os guses
    ios' = zip [opn..] nops
    opn' = opn + length ios'  

注意事項:

  1. 如果你想知道為什么我什至寫了這么大的 function 答案是:因為這是一些大的(編譯器中需要的功能): - 對於每個“返回變量”,我們應該找到最后一個操作,女巫定義它(實際上對應虛擬寄存器),並使用構造的操作擴展我們的 IR。

  2. 我見過一些類似的問題: Haskell 嵌套了 where 子句和“let... in”語法,但它們是關於“如何鍵入正確的代碼?”,而我的問題是“這個代碼代碼樣式是否正確,如果不是” t - 我該怎么辦?”。

並且沒有理由將其子功能放在模塊scope中

反過來想。 有什么理由把子功能放在本地scope中? 然后去做。 這可能是因為

  1. 它需要訪問本地綁定的變量。 在這種情況下,它必須是本地的,否則您需要額外的參數。
  2. 它做了一些非常明顯且僅與特定用例相關的事情。 這可能是某些操作的單行定義,您不需要考慮正確的描述性名稱,也可能是go助手,它基本上完成了封閉 function 的全部工作。

如果這些都不適用,您可以給本地 function 一個描述性名稱(正如您已經完成的那樣),然后將其放入模塊 scope 中。 添加類型簽名,使其更清晰。 不要從模塊中導出它。

將 function 放入模塊 scope 也無需像使用gdefs'那樣重命名變量。 這是 Haskell 代碼中的錯誤的更常見原因之一。

這個問題很好,但示例代碼不是一個很好的例子。 對我來說,在這種特殊情況下的正確解決方法是不要談論如何時尚地嵌套where s; 它是談論如何使用庫函數和語言特性來簡化代碼,以至於你不需要首先where 特別是,列表推導可以讓你走得很遠。 以下是我將如何編寫這兩個定義:

import Data.Containers.ListUtils (nubOrdOn)

... where
    ogs = [(o, gd) | (i, o) <- reverse ios, Just gd <- [gdefs M.!? i]]
    nops = nubOrdOn fun
        [ Oper GlobalUse g (RVar d) None
        | (Oper _ d _ _, g) <- ogs
        , g `elem` guses'
        ]
    fun (Oper _ g _ _) = g -- this seems useful enough to put at the global scope; it may even already exist there

由於代碼中的其他任何地方都沒有提到ogs ,因此您可以考慮將其內聯:

    -- delete the definition of ogs
    nops = nubOrdOn fun
        [ Oper GlobalUse g (RVar d) None
        | (i, Oper _ d _ _) <- reverse ios
        , Just g <- [gdefs M.!? i]
        , g `elem` guses'
        ]

暫無
暫無

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

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