考虑以下函数:
foo =
[1,2,3] >>=
return . (*2) . (+1)
为了更好的可读性和逻辑性,我想将我的纯函数移动(*2)
到(+1)
返回的左侧。我可以这样实现:
infixr 9 <.
(<.) :: (a -> b) -> (b -> c) -> (a -> c)
(<.) f g = g . f
bar =
[1,2,3] >>=
(+1) <.
(*2) <.
return
但是,我不喜欢(<.)
.
让我们介绍一个函数leftLift
:
leftLift :: Monad m => (a -> b) -> a -> m b
leftLift f = return . f
baz =
[1,2,3] >>=
leftLift (+1) >>=
leftLift (*2) >>=
return
我很喜欢这个。另一种可能性是定义 的变体bind
:
infixl 1 >>$
(>>$) :: Monad m => m a -> (a -> b) -> m b
(>>$) m f = m >>= return . f
qux =
[1,2,3] >>$
(+1) >>$
(*2) >>=
return
我不确定这是否是一个好主意,因为如果我想要的话,它不允许我使用do
符号。leftLift
我可以使用do
:
bazDo = do
x <- [1,2,3]
y <- leftLift (+1) x
z <- leftLift (*2) y
return z
我没有在 Hoogle 上找到签名为leftLift
. 这样的函数是否存在,如果存在,它叫什么?如果不是,我应该怎么称呼它?做我想做的事情最惯用的方式是什么?
编辑:以下是受@dunlop 回答启发的版本:
infixl 4 <&>
(<&>) :: Functor f => f a -> (a -> b) -> f b
(<&>) = flip fmap
blah =
[1,2,3] <&>
(+1) <&>
(*2) >>=
return
我还应该补充一点,我在使用bind
-variant,因为我想以无点风格编写我的代码。对于do
-notation,我想我不需要“假装”我正在做任何单子的事情,所以我可以使用let
s。