Haskell 帮助函数的好名字是什么?

Haskell 帮助函数的好名字是什么?,haskell,naming-conventions,Haskell,Naming Conventions,考虑以下问题:给定一个长度为三个元组(String,Int)的列表,是否有一对元素具有相同的“Int”部分?(例如,[(“bob”,5),(“gertrude”,3),(“al”,5)]包含这样一对,但是[(“bob”,5),(“gertrude”,3),(“al”,1)]不包含这样一对。) 这就是我将如何实现这样一个功能: import Data.List (sortBy) import Data.Function (on) hasPair::[(String,Int)]->Bool

考虑以下问题:给定一个长度为三个元组(String,Int)的列表,是否有一对元素具有相同的“Int”部分?(例如,
[(“bob”,5),(“gertrude”,3),(“al”,5)]
包含这样一对,但是
[(“bob”,5),(“gertrude”,3),(“al”,1)]
不包含这样一对。)

这就是我将如何实现这样一个功能:

import Data.List (sortBy)
import Data.Function (on)

hasPair::[(String,Int)]->Bool
hasPair = napkin . sortBy (compare `on` snd)
  where napkin [(_, a),(_, b),(_, c)] | a == b = True
                                      | b == c = True
                                      | otherwise = False
我使用模式匹配将名称绑定到元组的“Int”部分,但我想先排序(以便将类似的成员分组),因此我将模式匹配函数放在
where
子句中。但这就引出了我的问题:
where
子句中的函数选择名称的好策略是什么?我希望能很快想到这样的名字。在这个例子中,“hasPair”似乎是一个不错的选择,但它已经被采用了!我发现这种模式出现了很多次——辅助函数的自然名称已经被调用它的外部函数使用了。因此,我有时会将这些助手函数称为“op”、“foo”,甚至是“helper”——在这里,我选择了“napkin”来强调它的用途,一次就把它扔掉


那么,亲爱的读者们,你们会怎么称呼“餐巾”?更重要的是,您一般如何处理这个问题?

局部范围变量命名的一般规则

  • f
    k
    g
    h
    用于超简单的本地半匿名事物
  • go
    用于(尾部)递归帮助程序()
  • n
    m
    i
    j
    用于长度和大小以及其他数值
  • v
    获取地图查找和其他字典类型的结果
  • 字符串的
    s
    t
  • a:as
    x:xs
    y:ys
    用于列表
  • (a,b,c,)
    用于元组字段
这些通常只适用于HOFs的参数。对于你的情况,我会选择像
k
eq3
这样的东西


对于派生值,尽量少用撇号。

我倾向于调用布尔值函数
p
作为谓词<不幸的是,code>pred已经被采用了。

在这种情况下,内部函数基本上与外部函数相同,但前提条件不同(需要对列表进行排序),我有时会将相同的名称与素数一起使用,例如
hasPairs'

然而,在这种情况下,我更愿意尝试将问题分解为在顶层有用的部分。这通常也使命名它们更容易

hasPair :: [(String, Int)] -> Bool
hasPair = hasDuplicate . map snd

hasDuplicate :: Ord a => [a] -> Bool
hasDuplicate = not . isStrictlySorted . sort

isStrictlySorted :: Ord a => [a] -> Bool
isStrictlySorted xs = and $ zipWith (<) xs (tail xs)
hasPair::[(字符串,Int)]->Bool
hasPair=haspaire。地图snd
hasDuplicate::Ord a=>[a]->Bool
hasdeplicate=不是。是严格分类的。分类
IsStritlySorted::Ord a=>[a]->Bool

IsStritlySorted xs=和$zipWith(我的策略与Don的建议非常接近:

  • 如果有一个明显的名字,使用它
  • 如果是“工作者”或在其他方面与原始功能非常相似,则使用
    go
  • 根据上下文遵循个人约定,例如,对于折叠的args,遵循
    步骤
    开始
  • 如果其他方法都失败了,只需使用一个通用名称,如
    f
  • 我个人避免使用两种技巧。一种是使用原始函数的撇号版本,例如
    hasPair
    的where子句中的
    hasPair'
    。当你指的是另一个时,很容易意外地编写一个;在这种情况下,我更喜欢使用
    go
    。但这并不是一个大问题,只要函数ns有不同的类型。另一种是使用可能包含某些内容的名称,但与函数的实际功能无关。
    napkin
    将属于此类别。当您重新查看此代码时,此命名选择可能会让您感到困惑,因为您将忘记将其命名为
    napk的原始原因在
    (因为餐巾纸有四个角?因为它们很容易折叠?因为它们能清理垃圾?它们在餐馆里被发现?)其他的违例者是像
    bob和
    MyColfunc
    这样的东西


    如果你给了一个函数一个比
    go
    h
    更具描述性的名称,那么你应该能够查看它使用的上下文或函数体,并且在这两种情况下都能很好地理解为什么选择这个名称。这就是我的观点#3:个人约定。很多Don的建议适用。如果您在协作情况下使用Haskell,那么请与您的团队协调,并确定常见情况下的某些约定。

    go
    是一种方法:)一个通用指标-使用简短的描述性名称,如果您很难做到恰当的描述性,请尽量简短。顺便说一句,目前编写的
    napkin
    不是很可靠(列表中必须有三个成员),如果你再仔细想想,也许会建议一个更好的名称。@斯蒂芬:是的,我在编写时就意识到了这一点。但是,您是否会说这在总体上是正确的:如果您很难命名函数,那么您的设计可能需要改进?如果是真的,这是一个非常强大的概念…@gcbenison-对于顶级函数,我同意你的格言。复杂的名称是一个信号,表明某些东西还不够完善。在where close中定义的新hasPair不是优先并隐藏外部hasPair吗?在这么短的一段代码中,几乎没有混淆的风险…只是为了让阅读本文的人清楚:这些不是Haskell语言的规则,它们是(非常常见的)约定。
    k
    不是延续的常规名称吗?哦,是的,和
    p
    q
    表示谓词。
    m
    表示一元行为的参数