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

如何在Haskell中使用StateT Monad Transformers实现列表CRUD操作

实现示例

首先补全演示所需的SomeItem定义和依赖导入:

import Control.Monad.Trans.State.Strict (StateT, get, put, modify, runStateT)
import Data.List (find)

-- 补全SomeItem定义,用于演示CRUD逻辑
data SomeItem = SomeItem
  { itemId :: Int
  , content :: String
  } deriving (Eq, Show)

-- 你提供的原有类型定义
newtype SomeList = SomeList { items :: [SomeItem] }
  deriving (Show)

newtype SomeListStateT a = SomeListStateT 
  { runSomeListStateT :: StateT SomeList IO a 
  } deriving (Functor, Applicative, Monad, MonadIO)

CRUD操作实现

  • 新增元素(Create)
-- 向列表末尾追加单个元素
addItem :: SomeItem -> SomeListStateT ()
addItem newItem = SomeListStateT $ modify $ \(SomeList oldItems) ->
  SomeList (oldItems ++ [newItem])
  • 查询元素(Read)
-- 获取列表全部元素
getAllItems :: SomeListStateT [SomeItem]
getAllItems = SomeListStateT $ items <$> get

-- 按ID查询单个元素,无匹配返回Nothing
getItemById :: Int -> SomeListStateT (Maybe SomeItem)
getItemById targetId = do
  allItems <- getAllItems
  return $ find (\item -> itemId item == targetId) allItems
  • 修改元素(Update)
-- 按ID匹配更新元素,更新成功返回True,无匹配元素返回False
updateItem :: SomeItem -> SomeListStateT Bool
updateItem updatedItem = SomeListStateT $ do
  SomeList oldItems <- get
  let targetId = itemId updatedItem
      hasMatch = any (\i -> itemId i == targetId) oldItems
  if not hasMatch
    then return False
    else do
      let newItems = map (\i -> if itemId i == targetId then updatedItem else i) oldItems
      put $ SomeList newItems
      return True
  • 删除元素(Delete)
-- 按ID删除对应元素
deleteItemById :: Int -> SomeListStateT ()
deleteItemById targetId = SomeListStateT $ modify $ \(SomeList oldItems) ->
  SomeList $ filter (\item -> itemId item /= targetId) oldItems

测试运行示例

main :: IO ()
main = do
  -- 初始状态为空列表
  let initialState = SomeList []
  -- 执行组合的CRUD操作
  (res, finalState) <- runStateT (runSomeListStateT crudOps) initialState
  putStrLn $ "操作返回结果:" ++ show res
  putStrLn $ "最终列表状态:" ++ show finalState
  where
    crudOps = do
      -- 新增两个测试元素
      addItem $ SomeItem 1 "第一个元素"
      addItem $ SomeItem 2 "第二个元素"
      -- 打印新增后的全量数据
      allItems <- getAllItems
      liftIO $ putStrLn $ "新增后全部元素:" ++ show allItems
      -- 修改ID为1的元素
      updateSuccess <- updateItem $ SomeItem 1 "修改后的第一个元素"
      liftIO $ putStrLn $ "修改操作是否成功:" ++ show updateSuccess
      -- 查询ID为1的元素
      item1 <- getItemById 1
      liftIO $ putStrLn $ "查询ID为1的元素:" ++ show item1
      -- 删除ID为2的元素
      deleteItemById 2
      -- 返回剩余元素数量作为操作结果
      remaining <- getAllItems
      return $ length remaining

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 17:36:03