繁体   English   中英

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

[英]Does this simple Haskell function already have a well-known name?

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

unSndM :: Monad m => (a, m c) -> m (a, c)
unSndM (x, y) = do y' <- y
                   return (x, y')

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

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

unSndM' :: Monad m => (a, m c) -> m (a, c)
unSndM' (x, y) = y >>= return . (x,)

谢谢!

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

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

instance Foldable ((,) x) where
  foldMap = foldMapDefault

...然后这个(有时称为“强度”)将是Data.Traversable.sequence

sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)

所以

sequence :: (Monad m) => ((,) x) (m a) -> m (((,) x) a)

sequence :: (Monad m) => (x, m a) -> m (x, a)

实际上,序列并没有真正使用Monad的全部功能: Applicative会这样做。 此外,在这种情况下,与x配对是线性的,因此traverse仅仅<$>而不是pure<*>其他随机组合,并且(如在其他地方已经指出的那样)你只需要m来得到函数结构体。

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

unSndM :: (Functor f) => (a, f c) -> f (a, c)
unSndM (x, y) = fmap ((,) x) y

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

travis@sidmouth% pointfree "unSndM (x, y) = fmap ((,) x) y"
unSndM = uncurry (fmap . (,))

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

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

unSndM :: (Functor f) => (a, f c) -> f (a, c)
unSndM (x, y) = ((,) x) <$> y

<$>只是fmap的同义词,我喜欢它,这使得这是一种更清晰的函数应用程序。

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

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

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

Hoogle是你的朋友。 如果其中一个标准库有它,那么“ Monad m =>(a,mb) - > m(a,b) ”的hoogle会找到它。 请注意,该函数仍然可以在hackage包中,但对于像这样的小函数来说,通常不值得额外的build-dep。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM