为何我的PPMImage类型Functor实例定义报错?
解决你的PPMImage Functor实例错误
首先,咱们先揪出报错的核心问题:你写的f p这里类型完全不匹配!
你定义的f是a -> b类型的函数——它只能接受单个a类型的值,返回b类型的值。但你的p是[a]类型的像素列表,直接把整个列表塞给f,就相当于给一个只吃单个元素的函数递了一筐果子,Haskell当然会报错:它预期这里得到的是处理后的像素列表[b],但实际你强行喂给f列表后,得到的是单个b类型(甚至这一步根本走不通,因为类型不兼容),所以才会提示Couldn't match expected type ‘[b]’ with actual type ‘b’。
你理解的「解包-应用-重新包装」思路完全正确,但这里有个细节:你的pixels字段本身就是一个Functor(列表是Haskell内置的Functor实例),所以你需要借助列表的fmap把函数f逐个应用到像素列表的每个元素上,而不是直接把f作用在列表本身上。
正确的Functor实例应该这么写:
data PPMImage a = PPMImage {width :: Integer, height :: Integer, magicNumber :: Integer, maxColor :: Integer, pixels :: [a]} deriving (Show) instance Functor PPMImage where fmap f (PPMImage w h m c p) = PPMImage w h m c (fmap f p)
咱们拆解一下这个实现:
- 解包:从输入的
PPMImage里取出宽度w、高度h、魔数m、最大颜色值c和像素列表p - 应用:对像素列表
p调用fmap f——这会把f逐个应用到列表里的每一个a类型像素上,得到[b]类型的新像素列表 - 重新包装:用原来的元数据(宽、高、魔数、最大颜色值)加上处理后的新像素列表,构造出一个新的
PPMImage b
这样就完全符合Functor的设计了:它只修改容器(PPMImage)里的「内容」(像素列表的每个元素),而保留容器的其他结构信息完全不变。
内容的提问来源于stack exchange,提问作者hdizzle
相关产品推荐
相关产品推荐

