Haskell的lens包如何处理同时也是关键字的字段?

10

当一个去糖化的字段是一个关键字时,Lens如何处理?我记得读过一些特殊的处理方式,但我不记得在哪里读到的或“lensed”访问器的名称会变成什么。

考虑以下内容:

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}

import           Control.Lens
import           Control.Monad.IO.Class (liftIO)
import           Data.Maybe
import           Data.Aeson
import           Data.Aeson.TH
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy    as L
import qualified Data.ByteString.Lazy.Char8 as LC8
import qualified Data.Text.Lazy.Encoding as TLE


data Typ = Typ {
    _fld1 :: BS.ByteString
  , _type :: Int
} deriving (Show)

$(deriveJSON tail ''Typ)
$(makeLenses ''Typ)


main = do
  print $ typ^.fld1
  print $ typ^.getType
  where
    jsonTyp = "{\"fld1\": \"Test\", \"type\": 1 }"
    typ'    = decode jsonTyp  :: Maybe Typ
    typ     = fromJust typ'
    getType :: Getter Typ Int
    getType = to _type

_type访问器应该被称为什么,我如何避免在这里实现getType

我不得不在 school of haskell 上匆忙完成这个问题,因为我在这里没有访问一个合适的开发环境,但我想这可能对其他人有用。如果我能够进入ghci并执行:browse(如果这样可以得到答案),我会添加一个答案的,但与此同时,有人知道吗?

结论

谢谢大家,我将使用makeLensesWith以及关键词到替换的映射,根据 Edward 的建议。

2个回答

12

这并没有什么特别的。生成的透镜被命名为type,有趣的是,GHC似乎完全可以接受这一点。即使您使用完全限定名称,也可以使用它:

{-# LANGUAGE TemplateHaskell #-}    
module Foo where

import Control.Lens

data Bar = Bar { _type :: String }
  deriving Show

$(makeLenses ''Bar)

> :l Foo
> :t type      -- Um...
<interactive>:1:1: parse error on input `type'
> :t Foo.type  -- Haha!
Foo.type
  :: (Functor f, Profunctor p) =>
     p String (f String) -> p Bar (f Bar)
> Bar "hello" ^. Foo.type
"hello"

请注意,GHC 7.10 不再支持此功能。您不能再使用关键字名称生成镜头。有关示例,请参见此问题。 - Taylor Fausak

6

我通常只选择附近的字段名称。使用类似于_ty而不是_type的东西,然后产生的镜片是可调用的。

您还可以使用makeLensesWith提供自定义的名称转换函数。


谢谢Edward。在这种情况下,问题是字段名称来自Web服务的JSON(我正在自动生成数据声明)... 我想我也可以采用相同的方法进行From | ToJSON推导。 - Ben Ford
那么在这种情况下,镜头最终会做什么?它在这种情况下没有抛出错误,是_type被忽略了吗? - Ben Ford
1
它将使用模板哈斯克尔创建镜头,因为它直接构建语法树,而不需要解析,这样就可以正常工作。但是你不能不加限定地调用它。 - Edward Kmett
注意:您也可以手动编写 ty f (Bar a) = Bar <$> f a 镜头,并导出它。 - Edward Kmett
1
我不知道为什么花了这么长时间,但我刚刚注意到镜头构造和“遍历”构造是多么相似。更不用说你在派生页面上明确说明了这种相似性,而且我已经阅读过“Functor is to Lens as Applicative is to Biiplate”,一旦你开始使用“遍历”,它们之间的关系就非常明显了。当你只使用TH快捷方式时,语法上的对等性就会丢失,我想。 - J. Abrahamson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接