<*> 在 addRecip x y = fmap (+) (recipMay x) <*> recipMay y 中做了什么?
What does <*> do in addRecip x y = fmap (+) (recipMay x) <*> recipMay y?
addRecip :: Double -> Double -> Maybe Double
addRecip x y = fmap (+) (recipMay x) <*> recipMay y
where
recipMay a | a == 0 = Nothing
| otherwise = Just (1 / a)
我查找 <*>
的一些解释。
<*>
接受一个函子,其中包含一个接受 a
并返回 b
的函数,以及一个包含 a 的函子,它 returns 一个函子包含 a
b
。所以 <*>
从仿函数中提取函数并将其应用于仿函数内部的参数,最后 returns 将结果放入仿函数
这是一个例子:
fs <*> xs = [f x | f <- fs, x <- xs]
但就我而言,似乎有点不同。 recipMay x
中的元素不是函数。
这里的函子是Maybe
。 <*>
将 return Nothing
如果任一参数是 Nothing
(即,它涉及除以零)
Nothing <*> _ = Nothing
_ <*> Nothing = Nothing
在其余情况下,它只应用包装函数:
Just f <*> Just x = Just (f x)
另请注意
fmap (+) (recipMay x) <*> recipMay y
是一个有点不寻常的符号。通常写成
(+) <$> recipMay x <*> recipMay y
完全等价,因为 fmap
写成中缀 <$>
,但可以说更具可读性。
这里,fmap (+) (recipMay x)
(或(+) <$> recipMay x
)表示
if x == 0
then Nothing
else Just (\a -> 1/x + a)
<*> 将应用值应用于另一个。它是常规功能应用程序的更丰富的对应物。应用值以某种方式修饰,例如,是否有任何您认为的值(对于 Maybe,这是您的情况)可以是可选的,或者可以有很多值(对于 List)。
因此,将一个应用值应用到另一个应用值具有一些特殊行为。对于列表,a <*> b 将 a 的每个成员应用于 b 的每个成员,从而形成所有组合的巨大列表,而对于 Maybe(这是你的情况)a <*> b 给出 Just (a' b') 如果 a 和b 是 (Just a') 和 (Just b'),如果 a 和 b 中的一个或两者都不是 Nothing,则给出 Nothing - 对于 Maybe,总而言之,它是可选值的函数应用程序,如果涉及的任何值不存在,则结果不存在。
关于如何实施 <*> 有一些规则,这意味着您始终可以将其视为 [将 "contained function" 应用于 "contained value"],只要您完成所有工作在包含的域中(使用 <$>、<*>、pure、>>=、<|> 等)那么你可以认为它与常规函数应用程序相同,但是当你来到 "extract"价值,你会看到增加的丰富性。
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
来自 Applicative
类型类。 Applicative
是(引用文档)“A functor with application.”。您可以将 Functor
视为一个集合(尽管还有其他类型不是函子的集合,例如函数)。
如果我们将函子视为一个集合,那么 (<*>)
运算符将采用其中两个集合。第一个集合存储 a -> b
类型的函数,后者是 b
类型的集合。通过将第二个集合中的每个元素应用于第一个集合中的每个函数,结果是 b
s 的集合(相同类型的集合)。
所以对于列表来说,它看起来像:
(<*>) :: [a -> b] -> [a] -> [b]
(<*>) fs xs = [fi xj | fi <- fs, xj <- xs]
A Maybe
也是某种集合:它要么包含 no 元素(Nothing
的情况),要么包含 one 元素(具有 x
元素的 Just x
情况)。因此,您可以将 Maybe
视为具有“multiplicity” 0..1.
的集合
如果两个操作数之一是 Nothing
(或两者),则结果也是 Nothing
,因为如果没有函数或元素,则有没有"result"的一个函数应用。只有在两个操作数都是Just
的情况下(所以Just f
和Just x
),我们才能执行函数应用(所以Just (f x)
):
(<*>) :: Maybe (a -> b) -> Maybe a -> Maybe b
(<*>) (Just f) (Just x) = Just (f x)
(<*>) _ _ = Nothing
在这个具体案例中,我们可以分析一下用途:
addRecip :: Double -> Double -> Maybe Double
addRecip x y = (fmap (+) (recipMay x)) <*> recipMay y
where
recipMay a | a == 0 = Nothing
| otherwise = Just (1 / a)
因此我们看到两个操作数:fmap (+) (RecipMay x)
和 recipMay y
。如果x
and/ory
是0
,那么操作数分别是Nothing
。因为在那种情况下对应的 recipMay
是 Nothing
.
因此我们可以这样写:
addRecip :: Double -> Double -> Maybe Double
addRecip x y | x == 0 = Nothing
| y == 0 = Nothing
| otherwise = Just ((1/x) + (1/y))
但是在上面我们重复了== 0
和1/
逻辑两次。
addRecip :: Double -> Double -> Maybe Double
addRecip x y = fmap (+) (recipMay x) <*> recipMay y
where
recipMay a | a == 0 = Nothing
| otherwise = Just (1 / a)
我查找 <*>
的一些解释。
<*>
接受一个函子,其中包含一个接受 a
并返回 b
的函数,以及一个包含 a 的函子,它 returns 一个函子包含 a
b
。所以 <*>
从仿函数中提取函数并将其应用于仿函数内部的参数,最后 returns 将结果放入仿函数
这是一个例子:
fs <*> xs = [f x | f <- fs, x <- xs]
但就我而言,似乎有点不同。 recipMay x
中的元素不是函数。
这里的函子是Maybe
。 <*>
将 return Nothing
如果任一参数是 Nothing
(即,它涉及除以零)
Nothing <*> _ = Nothing
_ <*> Nothing = Nothing
在其余情况下,它只应用包装函数:
Just f <*> Just x = Just (f x)
另请注意
fmap (+) (recipMay x) <*> recipMay y
是一个有点不寻常的符号。通常写成
(+) <$> recipMay x <*> recipMay y
完全等价,因为 fmap
写成中缀 <$>
,但可以说更具可读性。
这里,fmap (+) (recipMay x)
(或(+) <$> recipMay x
)表示
if x == 0
then Nothing
else Just (\a -> 1/x + a)
<*> 将应用值应用于另一个。它是常规功能应用程序的更丰富的对应物。应用值以某种方式修饰,例如,是否有任何您认为的值(对于 Maybe,这是您的情况)可以是可选的,或者可以有很多值(对于 List)。
因此,将一个应用值应用到另一个应用值具有一些特殊行为。对于列表,a <*> b 将 a 的每个成员应用于 b 的每个成员,从而形成所有组合的巨大列表,而对于 Maybe(这是你的情况)a <*> b 给出 Just (a' b') 如果 a 和b 是 (Just a') 和 (Just b'),如果 a 和 b 中的一个或两者都不是 Nothing,则给出 Nothing - 对于 Maybe,总而言之,它是可选值的函数应用程序,如果涉及的任何值不存在,则结果不存在。
关于如何实施 <*> 有一些规则,这意味着您始终可以将其视为 [将 "contained function" 应用于 "contained value"],只要您完成所有工作在包含的域中(使用 <$>、<*>、pure、>>=、<|> 等)那么你可以认为它与常规函数应用程序相同,但是当你来到 "extract"价值,你会看到增加的丰富性。
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
来自 Applicative
类型类。 Applicative
是(引用文档)“A functor with application.”。您可以将 Functor
视为一个集合(尽管还有其他类型不是函子的集合,例如函数)。
如果我们将函子视为一个集合,那么 (<*>)
运算符将采用其中两个集合。第一个集合存储 a -> b
类型的函数,后者是 b
类型的集合。通过将第二个集合中的每个元素应用于第一个集合中的每个函数,结果是 b
s 的集合(相同类型的集合)。
所以对于列表来说,它看起来像:
(<*>) :: [a -> b] -> [a] -> [b]
(<*>) fs xs = [fi xj | fi <- fs, xj <- xs]
A Maybe
也是某种集合:它要么包含 no 元素(Nothing
的情况),要么包含 one 元素(具有 x
元素的 Just x
情况)。因此,您可以将 Maybe
视为具有“multiplicity” 0..1.
如果两个操作数之一是 Nothing
(或两者),则结果也是 Nothing
,因为如果没有函数或元素,则有没有"result"的一个函数应用。只有在两个操作数都是Just
的情况下(所以Just f
和Just x
),我们才能执行函数应用(所以Just (f x)
):
(<*>) :: Maybe (a -> b) -> Maybe a -> Maybe b
(<*>) (Just f) (Just x) = Just (f x)
(<*>) _ _ = Nothing
在这个具体案例中,我们可以分析一下用途:
addRecip :: Double -> Double -> Maybe Double
addRecip x y = (fmap (+) (recipMay x)) <*> recipMay y
where
recipMay a | a == 0 = Nothing
| otherwise = Just (1 / a)
因此我们看到两个操作数:fmap (+) (RecipMay x)
和 recipMay y
。如果x
and/ory
是0
,那么操作数分别是Nothing
。因为在那种情况下对应的 recipMay
是 Nothing
.
因此我们可以这样写:
addRecip :: Double -> Double -> Maybe Double
addRecip x y | x == 0 = Nothing
| y == 0 = Nothing
| otherwise = Just ((1/x) + (1/y))
但是在上面我们重复了== 0
和1/
逻辑两次。