当Haskell记录访问器以下划线引导时通常意味着什么?

时间:2012-10-05 12:25:06

标签: haskell

HaskellNet库中的一个例子:

data MailboxInfo = MboxInfo { _mailbox :: MailboxName
                            , _exists :: Integer
                            , _recent :: Integer
                            , _flags :: [Flag]
                            , _permanentFlags :: [Flag]
                            , _isWritable :: Bool
                            , _isFlagWritable :: Bool
                            , _uidNext :: UID
                            , _uidValidity :: UID
                            }
                 deriving (Show, Eq)

字段名称中的下划线是否意味着什么,如果不是编译器,那么至少根据Haskell惯例?

4 个答案:

答案 0 :(得分:25)

类似于表示不相关模式的下划线,例如fst (x, _) = x,下划线前缀(在记录字段或其他方面)用于指示读取代码的任何人都应忽略标识符,或者编译器可能忽略某些类型的用户交互,即使它已被给出出于某种原因的名字。

请注意,这不仅仅是一种约定,而是基于明确陈述in the Haskell Report

的内容
  

下划线,“_”被视为小写字母,可以出现在小写字母的任何地方。但是,“_”本身就是一个保留的标识符,在模式中用作通配符。鼓励为未使用的标识符提供警告的编译器禁止以下划线开头的标识符的此类警告。这允许程序员使用“_foo”作为他们期望未使用的参数。

一个例子是拟由Template Haskell使用的定义,然后定义没有下划线的等效标识符,如在基于记录字段生成镜头的常见示例中(我猜你的例子正在做什么) )。在这种情况下,标识符比实际定义更多地输入TH; TH生成的代码实际上可能使用也可能不使用下划线前缀标识符。

除了上述内容之外,下划线前缀与常规小写标识符没有任何不同。

答案 1 :(得分:10)

模板Haskell代码有时会查找以下划线开头的标识符。

For instance, underscores are used to automate lens generation.

答案 2 :(得分:2)

这只是一个很好的编程实践。

由于Haskell中的记录字段标签实际上是顶级命名函数,因此它们会污染模块命名空间。在字段标签中添加下划线意味着您可以自由定义另一个具有相同名称的函数。

答案 3 :(得分:2)

最近我发现了一些与您的问题相关的内容。

我想控制构造我的类型实例的位置,以证明每个值都是有效的。所以我在自己的模块中声明了它:

module Coords (Coords(), -- hide the constructor
               x,y,buildCoords) where

data Coords = Coords { x :: Int, y :: Int }

buildCoords :: Int -> Int -> Coords
buildCoords x y | x < 0 || y < 0 = error "omg"
buildCoords x y = Coords { x = x, y = y }

然后,我推断,从这个模块之外,没有代码可以创建无效的Coords。

我错了! xy是公开的,因此只需使用let c = buildCoords 1 1 in c { x = -1 }即可获得无效的Coords值!

但这种语法是唯一可能的,因为x和y是该类型的记录选择器。仅允许有效值的方法如下:

module Coords (Coords(), -- hide the constructor
               x,y,buildCoords) where

data Coords = Coords { _x :: Int, _y :: Int }
x = _x
y = _y

buildCoords :: Int -> Int -> Coords
buildCoords x y | x < 0 || y < 0 = error "omg"
buildCoords x y = Coords { _x = x, _y = y }

现在x和y只是常规函数。 c { x = -1 }语法将无法编译,其他模块无权访问记录选择器_x。

问题通过下划线解决; - )