Haskell中如何对含复杂对象的State类型实现map操作?
解决State类型的map函数实现问题
先看你定义的类型:
newtype State a = State (Stack a) deriving (Show) data Stack a = Active [a] | Inactive [a] deriving (Show)
你的需求是实现mapState函数,将传入的函数应用到State内部Stack嵌套的列表每个元素上。先分析你之前的错误:
- 第一段代码的问题:
f h : mapState f (State(Inactive t))中,f h是单个b类型值,而mapState返回State b,:是构造列表的运算符,两边类型完全不匹配,无法编译。 - 第二段代码的问题:模式匹配里写
State(Inactive (f h : t))是错误用法——模式匹配只能解构现有值,不能在模式中应用函数,Haskell会把这里的f当成新变量,导致类型不匹配;同时你没处理空列表的情况,会触发无限递归。
正确实现方式
我们需要先解构State拿到内部的Stack,针对Stack的两种构造器(Active/Inactive),分别取出里面的列表,用普通map处理每个元素,再重新包装成对应的Stack构造器,最后放回State中:
mapState :: (a -> b) -> State a -> State b mapState f (State stack) = State $ case stack of Active xs -> Active (map f xs) Inactive xs -> Inactive (map f xs)
如果想让逻辑更清晰,也可以把Stack的映射逻辑抽成辅助函数:
mapState :: (a -> b) -> State a -> State b mapState f (State stack) = State (mapStack f stack) where mapStack :: (a -> b) -> Stack a -> Stack b mapStack g (Active xs) = Active (map g xs) mapStack g (Inactive xs) = Inactive (map g xs)
另外注意:你原来类型签名里的(Eq b)是多余的,map操作不需要元素具备相等性,直接去掉即可。
内容的提问来源于stack exchange,提问作者chen
相关产品推荐
相关产品推荐

