Haskell中如何根据列表其他元素修改LocalType类型列表元素
实现方案
首先给出你提到的基础类型定义:
data Direction = Send | Receive deriving (Show, Eq, Ord, Read) data LocalType = Act Direction String LocalType | End deriving (Eq, Ord, Read)
实现思路
这个需求可以拆分为两步完成:
- 先遍历整个列表,统计所有存在的Send动作对应的字符串集合、Receive动作对应的字符串集合,两个集合的交集就是同时存在对应Send/Receive动作的字符串
- 再次遍历列表,只要元素的动作字符串属于上述交集,就替换为End,否则保留原元素
完全可以用foldr实现第二步的遍历逻辑。
完整代码实现
需要先导入Data.Set处理集合运算:
import qualified Data.Set as S import Data.Maybe (mapMaybe) -- 辅助函数:提取LocalType的动作信息,End返回空 getAction :: LocalType -> Maybe (Direction, String) getAction (Act dir s _) = Just (dir, s) getAction End = Nothing rule :: [LocalType] -> [LocalType] rule list = foldr processElem [] list where -- 提取所有动作 allActions = mapMaybe getAction list -- 统计所有Send、Receive对应的字符串集合 sendStrs = S.fromList [s | (Send, s) <- allActions] recvStrs = S.fromList [s | (Receive, s) <- allActions] -- 匹配成功的字符串集合(同时有Send和Receive) matchedStrs = S.intersection sendStrs recvStrs -- 处理单个元素的逻辑 processElem elem acc = case getAction elem of Just (_, s) | S.member s matchedStrs -> End : acc _ -> elem : acc
测试验证
用你给出的示例输入测试:
let list = [Act Send "a" End, Act Receive "a" End, Act Send "b" End] rule list -- 输出:[End,End,Act Send "b" End]
和你预期的输出完全一致。
内容的提问来源于stack exchange,提问作者polo
相关产品推荐
相关产品推荐

