在Haskell monad中使用纯函数/左举? [英] Using a pure function in a Haskell monad / left-lifting?

查看:120
本文介绍了在Haskell monad中使用纯函数/左举?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下功能:

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 lets.

推荐答案

每个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中使用纯函数/左举?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆