You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell中ST monad下HashTable与纯函数结合及遍历问题

使用ST Monad的HashTable实现词频统计

你的核心问题是**foldl是纯函数的折叠工具,无法直接处理ST Monad中的动作**——H.mutate返回的是ST s a类型的单子动作,而非纯值,自然不能作为foldl的累加器传递。要在ST语境下批量执行修改操作,需要用Monadic版本的遍历/折叠函数,比如mapM_或者foldM(均来自Control.Monad)。

关键修正点

  1. 用mapM_替代foldl:mapM_专门用于遍历列表并依次执行每个Monadic动作,不需要返回累加值,刚好适配你修改可变哈希表的场景。
  2. 简化mutate的处理逻辑:用maybe 1 (+1) v替代case表达式,更简洁地处理计数更新。
  3. 将ST语境中的哈希表转为纯值:ST中的可变结构无法直接导出,需用C.toList将其转换为纯的键值对列表,再通过runST提取结果。

修正后的完整代码

{-# LANGUAGE TupleSections #-}
import Data.Char(toLower)
import Data.Hashable(Hashable)
import Text.Regex.TDFA
import Control.Monad (mapM_, void)
import Control.Monad.ST
import qualified Data.HashTable.ST.Basic as H
import qualified Data.HashTable.Class as C

type HashTable s k v = H.HashTable s k v

st = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. "
re = "[a-z0-9]+"

count :: (Hashable k, Eq k) => [k] -> ST s (HashTable s k Int)
count ws = do
  ht <- H.new
  -- 遍历所有单词,更新哈希表计数
  mapM_ (\w -> H.mutate ht w $ \v -> (Just $ maybe 1 (+1) v, ())) ws
  return ht

main = do
  let wordsList = getAllTextMatches ((map toLower st) =~ re) :: [String]
      -- 运行ST动作,将哈希表转为纯键值对列表
      freqList = runST $ count wordsList >>= C.toList
  putStrLn $ show freqList

额外说明

  • H.mutate的第二个返回值可以是任意类型(这里用()表示不需要返回数据),它会被mapM_忽略。
  • 如果坚持用foldM,逻辑类似:
    count ws = do
      ht <- H.new
      void $ foldM (\ht w -> do
                       void $ H.mutate ht w $ \v -> (Just $ maybe 1 (+1) v, ())
                       return ht)
                   ht ws
      return ht
    
    但mapM_更符合这个场景的语义,因为我们不需要维护累加器的状态,只需要执行一系列修改动作。

内容的提问来源于stack exchange,提问作者Logrus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 11:53:17