gpt4 book ai didi

haskell - 使用lens、cosmosOf、uniplate 和 State monad 提取有关 AST 的信息

转载 作者:行者123 更新时间:2023-12-02 12:13:39 31 4
gpt4 key购买 nike

我有the following code遍历an AST使用cosmosOfuniplate寻找某种类型的节点。对于它找到的任何内容,它都会在记录中设置一个 Bool 标志,该标志在 the lens package 的帮助下使用 State monad 进行传播。 .

这一切都有效,但感觉相当严厉。感觉镜头、State monad 以及可能的 cosmosOf/uniplate 在这里可能都有些过分了。有更好或更惯用的方法来做到这一点吗?

{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TemplateHaskell #-}

module Docvim.Visitor.Section (getSectionInfo) where

import Control.Lens
import Control.Monad.State
import Data.Data.Lens (uniplate)
import Docvim.AST

data SectionInfo = SectionInfo { _hasCommand :: Bool
, _hasCommands :: Bool
, _hasFunction :: Bool
, _hasFunctions :: Bool
, _hasMapping :: Bool
, _hasMappings :: Bool
, _hasOption :: Bool
, _hasOptions :: Bool
} deriving (Show)

type Env = State SectionInfo

makeLenses ''SectionInfo

defaultSectionInfo :: SectionInfo
defaultSectionInfo = SectionInfo { _hasCommand = False
, _hasCommands = False
, _hasFunction = False
, _hasFunctions = False
, _hasMapping = False
, _hasMappings = False
, _hasOption = False
, _hasOptions = False
}

getSectionInfo :: Node -> SectionInfo
getSectionInfo n = execState (mapMOf_ (cosmosOf uniplate) check n) defaultSectionInfo
where
check (CommandAnnotation {}) = hasCommand .= True
check CommandsAnnotation = hasCommands .= True
check (FunctionAnnotation _) = hasFunction .= True
check FunctionsAnnotation = hasFunctions .= True
check (MappingAnnotation _) = hasMapping .= True
check MappingsAnnotation = hasMappings .= True
check (OptionAnnotation {}) = hasOption .= True
check OptionsAnnotation = hasOptions .= True
check _ = modify id

最佳答案

你想做的事可以通过para来完成来自 Uniplate 模块。

基本上,para 聚合从节点及其子节点收集的信息,并将其传递给节点的父节点以进行进一步聚合。

这是示例的简化版本 - 我们确定节点是否包含 CommandAnnotation 和/或 FunctionAnnotation 节点

import Data.Monoid
import qualified Data.Set as Set
import qualified Data.Generics.Uniplate.Data as Uniplate
import Data.Data

...

data HasSection = HasCommandAnnotation | HasFunction | HasOther
deriving (Show,Read,Enum,Bounded,Ord,Eq)

toHas :: Node -> HasSection
toHas (CommandAnnotation {}) = HasCommandAnnotation
toHas (FunctionsAnnotation {}) = HasFunction
toHas _ = HasOther

getSectionInfo :: Node -> Set.Set HasSection
getSectionInfo n = Uniplate.para visit n
where visit n res = Set.singleton (toHas n) <> mconcat res

README.md uniplate github 存储库通过示例对该库进行了很好的概述。

为了提高效率,您可以使用 bitset套装包装。

关于haskell - 使用lens、cosmosOf、uniplate 和 State monad 提取有关 AST 的信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37692177/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com