繁体   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