Haskell 哈斯克尔招摇过市镜头自动生成

Haskell 哈斯克尔招摇过市镜头自动生成,haskell,swagger,haskell-lens,Haskell,Swagger,Haskell Lens,我有以下代码: import Control.Lens ((&), (.~), (?~), (%~)) import Data.Swagger (Swagger) import Data.Swagger.Lens (paths, operationId, info, description) import qualified Data.HashMap.Strict.InsOrd as InsOrdHashMap import Data.Text (Text(..), pack) gen

我有以下代码:

import Control.Lens ((&), (.~), (?~), (%~))
import Data.Swagger (Swagger)
import Data.Swagger.Lens (paths, operationId, info, description)
import qualified Data.HashMap.Strict.InsOrd as InsOrdHashMap
import Data.Text (Text(..), pack)

genOpIds :: Swagger -> Swagger
genOpIds = paths %~ InsOrdHashMap.mapWithKey (\k v -> v & operationId ?~ (pack "hello"))
生成以下编译错误:

    • No instance for (Data.Swagger.Lens.HasOperationId
                         Data.Swagger.Internal.PathItem (Maybe Text))
        arising from a use of ‘operationId’
    • In the first argument of ‘(?~)’, namely ‘operationId’
      In the second argument of ‘(&)’, namely
        ‘operationId ?~ (pack "hello")’
      In the expression: v & operationId ?~ (pack "hello")
   |
12 | genOpIds = paths %~ InsOrdHashMap.mapWithKey (\k v -> v & operationId ?~ (pack "hello"))
   |                                                           ^^^^^^^^^^^
我发现诊断起来有点困难,因为我认为MakeLens用于生成类实例。我有点难以理解这与下面的(编译得很好)有什么不同:

因为所涉及的类型层次结构在底部是相似的。我怀疑这里缺少一点基本的理解,但我已经阅读了镜头教程,包括关于遍历的部分;各种各样的仆人招摇过市的代码,还有一些其他的例子,都还没有弄明白这一点

要轻松地重新创建错误消息,您可以克隆以下repo和
堆栈构建

https://github.com/msk-/improved-spork

免责声明:我从不招摇过市。 但是,查看文档,我可以看到招摇过市类型中的以下元素:
\u swaggerPaths::InsOrdHashMap FilePath PathItem
-对应于
路径
镜头。
查看
PathItem
的定义可以发现它不是
HasOperationId
的实例-它本身由

PathItem     
  _pathItemGet :: Maybe Operation   
  _pathItemPut :: Maybe Operation   
  _pathItemPost :: Maybe Operation  
  _pathItemDelete :: Maybe Operation    
  _pathItemOptions :: Maybe Operation   
  _pathItemHead :: Maybe Operation  
  _pathItemPatch :: Maybe Operation 
  _pathItemParameters :: [Referenced Param]
这似乎表明你在
(\k v->v&(???.operationId)~(pack“hello”)
;类似于
(\k v->v&(itemGet.operationId)~(pack“hello”)

编辑: 通过使用
PathItem
记录的
Monoid
实例,您试图实现的目标(设置一个简单的路径操作)看起来很容易实现,如下所示:

genOpsId = paths %~ InsOrdHashMap.mapWithKey (\k v -> v & get ?~ (mempty & operationId ?~ (pack "hello")))


编辑#2: 根据要求,这里有一种方法可以遍历
PathItem
记录的字段,并设置当前字段的操作ID。
为了记录在案,我非常肯定有一种方法,一种方法,一种更干净的方法来做到这一点,但现在开始

dokey :: PathItem -> PathItem
dokey v = foldl 
  (\acc nv -> acc & nv %~ (fmap $ operationId ?~ (pack "hello")))
  v 
  [get, put, post, delete, options, head_, patch]  

genOpIds :: Swagger -> Swagger
genOpIds = paths %~ InsOrdHashMap.mapWithKey (\k -> doKey)


希望有帮助!:)

您已经确定了问题所在,非常感谢。这有点尴尬,甚至和我想象的不一样!如您所见,PathItem可能包含多个操作。我想在任何存在操作ID的地方插入操作ID。我尝试过以各种组合使用traverse,以及每种组合,例如,
genOpsId=path%~InsOrdHashMap.mapWithKey(\k v->v.traverse?~(mempty&operationId?~(pack“hello”))
)。你知道我怎样才能做到吗?另外,我对
mempty&operationId
在做什么有点困惑,你知道我可能会读些什么来理解这一点吗?谢谢不要介意第二个问题,得到
mempty&operationId
位<代码>为了记录在案,我非常确定有一种方法,一种方法,一种更干净的方法可以做到这一点,但现在开始。哈哈,非常感谢!
dokey :: PathItem -> PathItem
dokey v = foldl 
  (\acc nv -> acc & nv %~ (fmap $ operationId ?~ (pack "hello")))
  v 
  [get, put, post, delete, options, head_, patch]  

genOpIds :: Swagger -> Swagger
genOpIds = paths %~ InsOrdHashMap.mapWithKey (\k -> doKey)