在 Haskell 中,是否有 (liftM . liftM)、(liftM . liftM . liftM) 等的别名?
In Haskell, are there aliases for (liftM . liftM), (liftM . liftM . liftM), etc?
在Haskell中,(liftM . liftM), (liftM . liftM . liftM)等有别名吗?
这样我就不用说得那么啰嗦了,例如:
(liftM . liftM) (+ 1) [Just 1, Just 2] = [Just 2, Just 3]
(liftM2 . liftM2) (+) [Just 1] [Just 2] = [Just 3]
base 中没有这样的东西,但是在 Stack Overflow 上问了我最有趣的问题已经有一段时间了。
Functors 和 Applicative functor 在组合下是封闭的(这对于 monad 来说通常不是这种情况,因此需要 monad 转换器),这就是 liftA2.liftA2
在这里工作的原因,liftM2
通常只是 liftA2
,尤其是现在 Applicative 正在成为 Monad 的超类。
题外话:
你可以使用 Data.Functor.Compose package to compose an Applicative, but you can make new applicatives out of old ones in other ways too - I strongly recommend Gershom Bazerman's post "Abstracting with Applicatives" in the Comonad Reader 中的组合 newtype 对于那些想要了解组合应用结构与 monad 转换器堆栈相比有多漂亮的人 - 我现在一直在寻找让事情变得只是应用而不是 monadic,我可以获得我需要的功能。通常我可以使用 Applicative 将所有输入的东西组合成一个我想要输出的值,然后将它直接通过管道传递给我
它将使用 >>=
。
您的函数和运算符
当然,没有什么能阻止您定义自己的函数:
liftliftA2 :: (Applicative f, Applicative g) =>
(a -> b -> c) -> f (g a) -> f (g b) -> f (g c)
liftliftA2 = liftA2.liftA2
但也比liftA2.liftA2
短不了多少。
虽然我喜欢你制作嵌套应用运算符的想法,但我会切换到增加尖括号而不是重复内部运算符,因为 <**>
与 Control.Applicative 中的 (<**>) = flip (<*>)
冲突, 而且更符合逻辑。
import Control.Applicative
(<<$>>) :: (Functor f, Functor g) =>
(a -> b) -> f (g a) -> f (g b)
(<<$>>) = fmap.fmap
(<<*>>) :: (Functor m, Applicative m, Applicative n) =>
m (n (a -> b)) -> m (n a) -> m (n b)
mnf <<*>> mna = (<*>) <$> mnf <*> mna
给予
ghci> (+) <<$>> [Just 5] <<*>> [Just 7,Just 10]
[Just 12,Just 15]
当然你可以继续:
(<<<$>>>) :: (Functor f, Functor g, Functor h) =>
(a -> b) -> f (g (h a)) -> f (g (h b))
(<<<$>>>) = fmap.fmap.fmap
(<<<*>>>) :: (Functor l,Functor m, Applicative l, Applicative m, Applicative n) =>
l (m (n (a -> b))) -> l (m (n a)) -> l (m (n b))
lmnf <<<*>>> lmna = (<*>) <<$>> lmnf <<*>> lmna
这让你可以做看似不可能的事
ghci> subtract <<<$>>> Right [Just 5,Nothing,Just 10] <<<*>>> Right [Just 100,Just 20]
Right [Just 95,Just 15,Nothing,Nothing,Just 90,Just 10]
但是话又说回来,正如 Gershom Bazerman 的文章所展示的,您可能希望嵌套 Applicatives,就像您希望嵌套 Monad 一样深。
在Haskell中,(liftM . liftM), (liftM . liftM . liftM)等有别名吗?
这样我就不用说得那么啰嗦了,例如:
(liftM . liftM) (+ 1) [Just 1, Just 2] = [Just 2, Just 3]
(liftM2 . liftM2) (+) [Just 1] [Just 2] = [Just 3]
base 中没有这样的东西,但是在 Stack Overflow 上问了我最有趣的问题已经有一段时间了。
Functors 和 Applicative functor 在组合下是封闭的(这对于 monad 来说通常不是这种情况,因此需要 monad 转换器),这就是 liftA2.liftA2
在这里工作的原因,liftM2
通常只是 liftA2
,尤其是现在 Applicative 正在成为 Monad 的超类。
题外话:
你可以使用 Data.Functor.Compose package to compose an Applicative, but you can make new applicatives out of old ones in other ways too - I strongly recommend Gershom Bazerman's post "Abstracting with Applicatives" in the Comonad Reader 中的组合 newtype 对于那些想要了解组合应用结构与 monad 转换器堆栈相比有多漂亮的人 - 我现在一直在寻找让事情变得只是应用而不是 monadic,我可以获得我需要的功能。通常我可以使用 Applicative 将所有输入的东西组合成一个我想要输出的值,然后将它直接通过管道传递给我
它将使用 >>=
。
您的函数和运算符
当然,没有什么能阻止您定义自己的函数:
liftliftA2 :: (Applicative f, Applicative g) =>
(a -> b -> c) -> f (g a) -> f (g b) -> f (g c)
liftliftA2 = liftA2.liftA2
但也比liftA2.liftA2
短不了多少。
虽然我喜欢你制作嵌套应用运算符的想法,但我会切换到增加尖括号而不是重复内部运算符,因为 <**>
与 Control.Applicative 中的 (<**>) = flip (<*>)
冲突, 而且更符合逻辑。
import Control.Applicative
(<<$>>) :: (Functor f, Functor g) =>
(a -> b) -> f (g a) -> f (g b)
(<<$>>) = fmap.fmap
(<<*>>) :: (Functor m, Applicative m, Applicative n) =>
m (n (a -> b)) -> m (n a) -> m (n b)
mnf <<*>> mna = (<*>) <$> mnf <*> mna
给予
ghci> (+) <<$>> [Just 5] <<*>> [Just 7,Just 10]
[Just 12,Just 15]
当然你可以继续:
(<<<$>>>) :: (Functor f, Functor g, Functor h) =>
(a -> b) -> f (g (h a)) -> f (g (h b))
(<<<$>>>) = fmap.fmap.fmap
(<<<*>>>) :: (Functor l,Functor m, Applicative l, Applicative m, Applicative n) =>
l (m (n (a -> b))) -> l (m (n a)) -> l (m (n b))
lmnf <<<*>>> lmna = (<*>) <<$>> lmnf <<*>> lmna
这让你可以做看似不可能的事
ghci> subtract <<<$>>> Right [Just 5,Nothing,Just 10] <<<*>>> Right [Just 100,Just 20]
Right [Just 95,Just 15,Nothing,Nothing,Just 90,Just 10]
但是话又说回来,正如 Gershom Bazerman 的文章所展示的,您可能希望嵌套 Applicatives,就像您希望嵌套 Monad 一样深。