【问题标题】:Does this simple Haskell function already have a well-known name?这个简单的 Haskell 函数是否已经有了一个众所周知的名字?
【发布时间】:2010-10-22 15:04:32
【问题描述】:

我刚刚编写了这个函数,它只接受第二个值在某个 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,)

谢谢!

【问题讨论】:

标签: haskell tuples monads


【解决方案1】:

如果 (,) 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 可以。此外,在这种情况下,pairing-with-x 是线性的,所以traverse 只做&lt;$&gt; 而不是pure&lt;*&gt; 的其他随机组合,并且(正如在别处指出的那样)你只需要m 具有函数结构。

【讨论】:

  • 对我来说听起来像是图书馆@提案的诞生 :-)
  • 惊人的东西。我知道它看起来很简单,类别理论家一定已经给它起了名字。 :-)
  • 不是很简单,但是在 (Data.)Traversible 中定义了一个 'sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a)' .我想既然你提到“你只需要......函数结构”,你可以使用它。
【解决方案2】:

一个小问题:可以只使用fmap(没有&gt;&gt;=)来写这个,所以你真的只需要一个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&lt;$&gt;,它确实会减少一个字符:

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

&lt;$&gt; 只是fmap 的同义词,我喜欢它使这是一种功能应用程序的事实更加清晰。

【讨论】:

  • 元组的排序也很方便,允许像unSmdM = uncurry $ fmap . (,) 这样的定义。有趣的是,这个函数的类型比任何一个实现都更具可读性/描述性:)
  • 我同意,但unSndM (x, y) = (x,) &lt;$&gt; y 非常接近。
  • 哦,我不知道 pointfree - 很好,谢谢! (当然,我试过 hoogle。)这里有一些不错的版本,没有任何额外的导入或对库的修改 ;-) - 谢谢。 :-)
  • 感谢pointfree 的提示。我一直在#haskell 上使用@pl 和lambdabot。
  • 我就是喜欢无点。它应该是每个 Haskell IDE 的一部分。
【解决方案3】:

我还没有在任何 Haskell 库中看到过它(尽管它可能在 category-extras 中),但它通常被称为 monad 的“张量强度”。见:

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

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

【讨论】:

    【解决方案4】:

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

    【讨论】:

    • “对于这样的小功能,通常不值得额外的构建dep”
    猜你喜欢
    • 2013-08-24
    • 1970-01-01
    • 2011-02-07
    • 1970-01-01
    • 2011-11-23
    • 2014-11-09
    • 2011-02-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多