问题描述
考虑以下功能:
foo =
[1,2,3] >>=
return . (*2) . (+1)
为了更好的可读性和逻辑性,我想将纯函数(*2)
和(+1)
移到返回的左侧.我可以这样实现:
For better readability and logic, I would like to move my pure functions (*2)
and (+1)
to the left of the return. I could achieve this like this:
infixr 9 <.
(<.) :: (a -> b) -> (b -> c) -> (a -> c)
(<.) f g = g . f
bar =
[1,2,3] >>=
(+1) <.
(*2) <.
return
但是,我不喜欢(<.)
的右关联性.
However, I don't like the right-associativity of (<.)
.
让我们介绍一个函数leftLift
:
leftLift :: Monad m => (a -> b) -> a -> m b
leftLift f = return . f
baz =
[1,2,3] >>=
leftLift (+1) >>=
leftLift (*2) >>=
return
我很喜欢这样.另一种可能性是定义bind
的变体:
I quite like this. Another possibility would be to define a variant of 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
一起使用:
I am not sure whether that is a good idea, since it would not allow me to use do
notation should I want that. leftLift
I can use with do
:
bazDo = do
x <- [1,2,3]
y <- leftLift (+1) x
z <- leftLift (*2) y
return z
我没有在Hoogle上找到带有leftLift
签名的函数.是否存在这样的功能,如果称之为,该功能是什么?如果没有,我应该怎么称呼它?而做我想做的最惯用的方式是什么?
I didn't find a function on Hoogle with the signature of leftLift
. Does such a function exist, and, if, what is it called? If not, what should I call it? And what would be the most idiomatic way of doing what I am trying to do?
这是一个受@dunlop的回答启发的版本:
Here's a version inspired by @dunlop's answer below:
infixl 4 <&>
(<&>) :: Functor f => f a -> (a -> b) -> f b
(<&>) = flip fmap
blah =
[1,2,3] <&>
(+1) <&>
(*2) >>=
return
我还应该补充一点,我是在bind
-variant之后,因为我想以无点样式编写代码.对于do
表示法,我想我不需要假装"我正在做任何事,所以我可以使用let
s.
I should also add that I was after a bind
-variant, because I wanted to write my code in point-free style. For do
-notation, I guess I don't need to "pretend" that I'm doing anything monadic, so I can use let
s.
推荐答案
每个Monad
都是Functor
(也是Applicative
).您的(>>$)
是(翻转)fmap
.
Every Monad
is a Functor
(and an Applicative
too). Your (>>$)
is (flipped) fmap
.
GHCi> :t fmap
fmap :: Functor f => (a -> b) -> f a -> f b
GHCi> :t (<$>) -- Infix synonym for 'fmap'
(<$>) -- Infix synonym for 'fmap'
:: Functor f => (a -> b) -> f a -> f b
GHCi> fmap ((*2) . (+1)) [1,2,3]
[4,6,8]
GHCi> (*2) . (+1) <$> ([1,2,3] >>= \x -> [1..x])
[4,4,6,4,6,8]
(顺便说一下,翻转的fmap
的通用名称是(<&>)
.例如, lens 称之为它.)
(By the way, a common name for flipped fmap
is (<&>)
. That is, for instance, what lens calls it.)
如果使用的是do-notation,则没有理由明确地使用fmap
的任何变体进行这种转换.只需将您的<-
单子绑定切换为let-bindings:
If you are using do-notation, there is little reason to use any variant of fmap
explicitly for this kind of transformation. Just switch your <-
monadic bindings for let-bindings:
bazDo = do
x <- [1,2,3]
let y = (+1) x
z = (*2) y
return z
bazDo = do
x <- [1,2,3]
let y = (+1) x
return ((*2) z)
这篇关于在Haskell monad中使用纯函数/左举?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!