J'ai the following code qui traverse an AST en utilisant cosmosOf
et uniplate
en recherchant des nœuds d'un certain type. Pour tout ce qu'il trouve, il définit un drapeau Bool
dans un enregistrement qui est propagé en utilisant une monade State
à l'aide de the lens
package.Utilisation de la lentille, cosmosOf, uniplate, et l'état Monad pour extraire des informations sur un AST
Tout cela fonctionne, mais se sent assez lourd. Il se sent comme des lentilles, la monade State
, et peut-être cosmosOf
/uniplate
peut-être être exagéré ici. Y a-t-il une façon meilleure ou plus idiomatique de le faire?
{-# 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
Il existe également un [para] (https://hackage.haskell.org/package/lens/docs/Control-Lens-Plated.html#v:para) pour 'Plated', l'équivalent de' Uniplate' dans le paquet de lentilles. – Cirdec