Functor #
一、Functor概念 #
1.1 什么是Functor #
Functor是可以被映射的类型构造器:
haskell
class Functor f where
fmap :: (a -> b) -> f a -> f b
1.2 类型签名 #
haskell
-- fmap将函数应用于"容器"内的值
fmap :: (a -> b) -> f a -> f b
-- 类比
-- map :: (a -> b) -> [a] -> [b]
-- fmap是map的泛化版本
1.3 简单示例 #
haskell
-- Maybe是Functor
instance Functor Maybe where
fmap _ Nothing = Nothing
fmap f (Just x) = Just (f x)
-- 使用
fmap (*2) (Just 5) -- Just 10
fmap (*2) Nothing -- Nothing
二、常见Functor实例 #
2.1 Maybe #
haskell
-- Maybe实例
instance Functor Maybe where
fmap _ Nothing = Nothing
fmap f (Just x) = Just (f x)
-- 使用
fmap show (Just 42) -- Just "42"
fmap length (Just "hello") -- Just 5
fmap (+1) Nothing -- Nothing
2.2 列表 #
haskell
-- 列表实例
instance Functor [] where
fmap = map
-- 使用
fmap (*2) [1, 2, 3] -- [2, 4, 6]
fmap show [1, 2, 3] -- ["1", "2", "3"]
2.3 Either #
haskell
-- Either实例
instance Functor (Either e) where
fmap _ (Left x) = Left x
fmap f (Right y) = Right (f y)
-- 使用
fmap (*2) (Right 5 :: Either String Int) -- Right 10
fmap (*2) (Left "error" :: Either String Int) -- Left "error"
2.4 IO #
haskell
-- IO实例
instance Functor IO where
fmap f action = do
x <- action
return (f x)
-- 使用
main :: IO ()
main = do
line <- fmap (map toUpper) getLine
putStrLn line
2.5 元组 #
haskell
-- 二元组实例(只映射第二个元素)
instance Functor ((,) a) where
fmap f (x, y) = (x, f y)
-- 使用
fmap (*2) (1, 5) -- (1, 10)
fmap show (True, 42) -- (True, "42")
三、Functor定律 #
3.1 恒等律 #
haskell
-- 恒等律
-- fmap id == id
-- 验证
fmap id (Just 5) -- Just 5
id (Just 5) -- Just 5
fmap id [1, 2, 3] -- [1, 2, 3]
id [1, 2, 3] -- [1, 2, 3]
3.2 组合律 #
haskell
-- 组合律
-- fmap (f . g) == fmap f . fmap g
-- 验证
fmap (show . (*2)) (Just 5) -- Just "10"
(fmap show . fmap (*2)) (Just 5) -- Just "10"
3.3 定律的重要性 #
haskell
-- 符合定律的实现行为可预测
-- 不符合定律的实现可能导致意外行为
-- 错误示例(违反定律)
-- instance Functor Maybe where
-- fmap _ _ = Nothing -- 违反恒等律
四、<$>运算符 #
4.1 运算符形式 #
haskell
-- <$> 是fmap的中缀形式
(<$>) :: Functor f => (a -> b) -> f a -> f b
-- 使用
(*2) <$> Just 5 -- Just 10
show <$> [1, 2, 3] -- ["1", "2", "3"]
4.2 与$对比 #
haskell
-- $ 用于普通函数应用
(*2) $ 5 -- 10
-- <$> 用于Functor映射
(*2) <$> Just 5 -- Just 10
4.3 链式操作 #
haskell
-- 链式fmap
show . (*2) <$> Just 5 -- Just "10"
-- 多个Functor操作
addMaybe :: Maybe Int -> Maybe Int -> Maybe Int
addMaybe x y = (+) <$> x <*> y
-- 需要Applicative
五、<$运算符 #
5.1 替换值 #
haskell
-- <$ 用值替换Functor内容
(<$) :: Functor f => a -> f b -> f a
-- 使用
1 <$ Just 5 -- Just 1
1 <$ Nothing -- Nothing
'a' <$ [1, 2, 3] -- ['a', 'a', 'a']
5.2 实现原理 #
haskell
-- <$ 实现
x <$ fa = const x <$> fa
-- 示例
1 <$ Just 5
= const 1 <$> Just 5
= Just (const 1 5)
= Just 1
六、函数作为Functor #
6.1 实例定义 #
haskell
-- 函数是Functor(reader functor)
instance Functor ((->) r) where
fmap = (.)
-- 类型签名
-- fmap :: (a -> b) -> ((->) r a) -> ((->) r b)
-- 等价于
-- fmap :: (a -> b) -> (r -> a) -> (r -> b)
-- 即函数组合
6.2 使用 #
haskell
-- 函数作为Functor
fmap (*2) (+1) 5 -- 12
-- 等价于
(*2) . (+1) $ 5 -- 12
-- 链式
fmap show (+1) 5 -- "6"
show . (+1) $ 5 -- "6"
七、实践示例 #
7.1 处理Maybe值 #
haskell
-- 安全操作链
safeDiv :: Int -> Int -> Maybe Int
safeDiv _ 0 = Nothing
safeDiv x y = Just (x `div` y)
-- 使用fmap
process :: Int -> Int -> Maybe String
process x y = show <$> safeDiv x y
-- 使用
process 10 2 -- Just "5"
process 10 0 -- Nothing
7.2 处理列表 #
haskell
-- 数据转换管道
processData :: [Int] -> [String]
processData = fmap show . fmap (*2) . filter even
-- 等价于
processData' = map show . map (*2) . filter even
-- 使用
processData [1..10] -- ["4", "8", "12", "16", "20"]
7.3 处理Either #
haskell
-- 错误处理链
validate :: Int -> Either String Int
validate x
| x < 0 = Left "Negative"
| x > 100 = Left "Too large"
| otherwise = Right x
-- 使用fmap
process :: Int -> Either String String
process x = show <$> validate x
-- 使用
process 50 -- Right "50"
process (-1) -- Left "Negative"
7.4 处理IO #
haskell
-- IO操作链
readAndProcess :: IO String
readAndProcess = processLine <$> getLine
where
processLine = reverse . map toUpper
main :: IO ()
main = do
result <- readAndProcess
putStrLn result
八、Functor组合 #
8.1 嵌套Functor #
haskell
-- 嵌套Functor
nested :: Maybe [Int]
nested = Just [1, 2, 3]
-- 两层fmap
fmap (fmap (*2)) nested -- Just [2, 4, 6]
-- 使用<$>
(*2) <$> (*2) <$> nested -- Just [4, 8, 12]
8.2 Compose类型 #
haskell
-- Compose包装器
newtype Compose f g a = Compose { getCompose :: f (g a) }
instance (Functor f, Functor g) => Functor (Compose f g) where
fmap f (Compose x) = Compose (fmap (fmap f) x)
-- 使用
-- fmap (*2) (Compose (Just [1, 2, 3]))
-- Compose (Just [2, 4, 6])
九、总结 #
Functor要点:
- 定义:
fmap :: (a -> b) -> f a -> f b - 常见实例:Maybe、[]、Either、IO、元组
- 定律:恒等律、组合律
- 运算符:
<$>(fmap)、<$(替换) - 函数Functor:
fmap = (.) - 嵌套:可以多层fmap
掌握Functor后,让我们继续学习Applicative。
最后更新:2026-03-27