如何利用Haskell State Monad生成替换后的目标整数列表?
解决Haskell State Monad同时生成转换列表和计数的问题
你的代码目前只返回了计数结果,核心问题在于终止条件返回的是计数而非处理后的元素列表,且递归时没有将当前元素的转换结果与后续列表拼接。下面是修改后的完整方案:
修正后的代码
module Main( main ) where import Control.Monad.State l = [ Right 6, Left "AAA", Right 3, Right 8, Left "CCC", Right 2, Right 9, Right 1, Left "D"] scanList :: [ Either String Int ] -> State (Int,Int) [ Int ] scanList [] = return [] -- 遍历结束时返回空列表,计数保留在State中 scanList (x:xs) = do (ns, ni) <- get -- 一次匹配x,同时获取新状态和当前元素的转换值 let (newState, currentVal) = case x of Left _ -> ((ns + 1, ni), 0) -- Left类型:字符串计数+1,转换为0 Right i -> ((ns, ni + 1), i) -- Right类型:整数计数+1,保留原值 put newState -- 更新状态 rest <- scanList xs -- 递归处理剩余元素 return (currentVal : rest) -- 拼接当前值和后续结果 startState = (0,0) main = do -- 使用runState同时获取处理后的列表和最终计数状态 let (processedList, (strCount, intCount)) = runState (scanList l) startState putStrLn $ "目标列表: " ++ show processedList putStrLn $ "统计结果: 字符串数量=" ++ show strCount ++ ", 整数数量=" ++ show intCount
关键改动说明
- 终止条件调整:原代码终止时返回
[ns,ni](计数列表),现在改为返回空列表[],因为遍历完成后没有更多元素需要加入结果,计数会保存在State的最终状态中。 - 递归逻辑修正:
- 不再重复匹配
x,而是一次匹配同时得到新的状态和当前元素的转换值,更简洁高效。 - 递归处理剩余元素后,将当前转换值与递归结果拼接(
currentVal : rest),确保所有元素都被加入结果列表。
- 不再重复匹配
- 结果获取方式:使用
runState替代evalState,这样可以同时拿到处理后的列表和最终的计数状态(字符串数、整数数)。
运行这段代码后,你会得到:
目标列表: [6,0,3,8,0,2,9,1,0] 统计结果: 字符串数量=3, 整数数量=6
内容的提问来源于stack exchange,提问作者OrenIshShalom
相关产品推荐
相关产品推荐

