[英]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)
的Traversable
和Foldable
实例在库中(我想我必须为他们的缺席负责)...
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.