它是fmap. 我喜欢将其视为可以将(大多数人说是提升)纯函数带入某些上下文的东西,只要该上下文是函子(并且大多数具有类型参数的数据类型都可以变成函子)。
例如,假设您有一个函数
double :: Int -> Int
double x = 2 * x
Run Code Online (Sandbox Code Playgroud)
但您正在处理Maybe列表中的值[Nothing, Just 3, Just 1, Nothing, Just 0]。你想把每个Just-number 都加倍,但你不知道怎么做。
您知道map列表中有,但是如何处理Maybes?
你可以写
doubleList :: [Maybe Int] -> [Maybe Int]
doubleList = map doubleMaybe
where doubleMaybe (Just n) = Just (2*n)
doubleMaybe Nothing = Nothing
Run Code Online (Sandbox Code Playgroud)
但这似乎很愚蠢,因为你已经有了 double
这里谈到fmap发挥作用-fmap 升降机 double为Maybe:fmap double :: Maybe Int -> Maybe Int:
doubleList :: [Maybe Int] -> [Maybe Int]
doubleList = map (fmap double)
Run Code Online (Sandbox Code Playgroud)
或者作为一个列表也是一个函子
doubleList :: [Maybe Int] -> [Maybe Int]
doubleList = fmap (fmap double)
Run Code Online (Sandbox Code Playgroud)
或者
doubleList :: [Maybe Int] -> [Maybe Int]
doubleList = (fmap . fmap) double
Run Code Online (Sandbox Code Playgroud)
<$>如果你有积分就派上用场- 所以fmap double (Just 5) = double <$> Just 5。
您经常在IO计算(将一些函数提升到IO)和应用程序中看到这一点。
为此,让我们看看
add :: Int -> Int -> Int
add = (+)
Run Code Online (Sandbox Code Playgroud)
如何将两个包裹在里面的数字相加Maybe?
在这里<$>,<*>真的很方便:
> add <$> Just 4 <*> Just 5
Just 9
> add <$> Just 4 <*> Nothing
Nothing
> add <$> Nothing <*> Just 5
Nothing
> add <$> Nothing <*> Nothing
Nothing
Run Code Online (Sandbox Code Playgroud)
IMO 应用程序并不是立即学习那么重要。通常你可以使用do符号来写那些,而且从我所看到的初学者 - 特别是来自更多命令式语言 - 没有问题:
... do
a <- Just 4
b <- Just 5
pure $ add a b
Run Code Online (Sandbox Code Playgroud)
但Functor真的无处不在——我想这是一个习惯的问题。
如果你看到 aSomeType a并且你想要 aSomeType b并且你知道如何a -> b或者如果你想要 aSomeType a -> SomeType b并且知道/拥有a -> b- Functor,fmap并且<$>应该立即出现在你的脑海中。