这个简单的Haskell函数是否已经有一个众所周知的名字?

gim*_*and 8 monads haskell tuples

我刚刚编写了这个函数,它只需要一对第二个值在一些monad中,并"拉出monad"来覆盖整个对.

unSndM :: Monad m => (a, m c) -> m (a, c)
unSndM (x, y) = do y' <- y
                   return (x, y')
Run Code Online (Sandbox Code Playgroud)

是否有更好的和/或更短或无点甚至标准的表达方式?

打开-XTupleSections后,我已经达到以下目的了...

unSndM' :: Monad m => (a, m c) -> m (a, c)
unSndM' (x, y) = y >>= return . (x,)
Run Code Online (Sandbox Code Playgroud)

谢谢!

pig*_*ker 13

如果TraversableFoldable实例(,) x)在库中(我想我必须为他们的缺席负责)...

instance Traversable ((,) x) where
  traverse f (x, y) = (,) x <$> f y

instance Foldable ((,) x) where
  foldMap = foldMapDefault
Run Code Online (Sandbox Code Playgroud)

...然后这个(有时称为"力量")将是一个专业化Data.Traversable.sequence.

sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)
Run Code Online (Sandbox Code Playgroud)

所以

sequence :: (Monad m) => ((,) x) (m a) -> m (((,) x) a)
Run Code Online (Sandbox Code Playgroud)

sequence :: (Monad m) => (x, m a) -> m (x, a)
Run Code Online (Sandbox Code Playgroud)

事实上,序列并没有真正使用的全部功能Monad:Applicative将会这样做.此外,在这种情况下,配对与- x是线性的,所以traverse只做<$>而不是其他随机组合pure<*>,以及(如已经指出的其他地方),你只需要m拥有函子结构.


Tra*_*own 12

一个小问题:可以仅使用fmap(no >>=)编写它,所以你真的只需要一个Functor实例:

unSndM :: (Functor f) => (a, f c) -> f (a, c)
unSndM (x, y) = fmap ((,) x) y
Run Code Online (Sandbox Code Playgroud)

这个版本有点笼统.要回答关于无点版本的问题,我们可以问pointfree:

travis@sidmouth% pointfree "unSndM (x, y) = fmap ((,) x) y"
unSndM = uncurry (fmap . (,))
Run Code Online (Sandbox Code Playgroud)

所以,是的,更短的版本是可能的,但我个人觉得uncurry有点难以阅读并在大多数情况下避免它.

如果我在自己的代码中编写这个函数,我可能会使用<$>from Control.Applicative,这会削减一个字符:

unSndM :: (Functor f) => (a, f c) -> f (a, c)
unSndM (x, y) = ((,) x) <$> y
Run Code Online (Sandbox Code Playgroud)

<$>只是一个同义词fmap,我喜欢它使事实这是一种更清晰的功能应用程序.


mok*_*kus 8

我没有看到它写在任何Haskell库中(虽然它可能在类别附加),但它通常被称为monad的"张力".看到:

http://en.wikipedia.org/wiki/Strong_monad

http://comonad.com/reader/2008/deriving-strength-from-laziness/