【问题标题】:How to convert a failed computation to a successful one and vice versa如何将失败的计算转换为成功的计算,反之亦然
【发布时间】:2012-10-20 06:20:06
【问题描述】:

这很可能是一个寻求问题的解决方案......如果是这样,我请求你的宽容!

可能的实现:

class Switch' f where
  switch :: f a -> f ()

instance Switch' [] where
  switch []     = [()]
  switch (_:_)  = []

instance Switch' Maybe where
  switch Nothing   = Just ()
  switch (Just _)  = Nothing

解释是:给定一个成功的计算,让它失败;给定一个失败的计算,让它成功。我不确定,但这似乎与 MonadPlus 正好相反……如果你眯着眼睛真的很用力的话。 ???

这个概念有标准类型类或其他实现吗?如果有的话,底层数学会是什么样子(即这是一个半群、一个循环等)?

【问题讨论】:

  • switch 几乎是二阶元素 - 它几乎是自逆的,因为 switch.switch.switch = switch.switch。它最终生成重复的轨道(尽管最终是正确的词,但在提到等待 1 次迭代时听起来很长)。 switch.switch 是幂等的。这就是我刚才想在 switch 上抛出的所有数学。
  • 是什么让[()] 更适合返回,而不是[(),()..]
  • 它是return (),和另一个例子一样。
  • @AndrewC 也许法律规定switch 专用于m () -> m ()involution
  • @PetrPudlák 是的,我认为这是完美的表达方式。好决定。由于switch :: Switch m => m a -> m (),我们知道switch x :: m (),所以我说的所有这些都自动保留。非常整洁。对合也是一个比我使用的更好的术语。

标签: haskell typeclass alternative-functor monadplus


【解决方案1】:
switch :: (Alternative f, Eq (f a)) => f a -> f ()
switch x | x == empty = pure ()
         | otherwise = empty

switch :: (MonadPlus m, Eq (m a)) => m a -> m ()
switch x | x == mzero = return ()
         | otherwise = mzero

【讨论】:

  • @MattFenwick 我的错误,我已经解决了。
  • Eq 约束是不幸的
  • 当我的数据结构包含函数,或者其他不是Eq-able的东西时,我该怎么办?
  • @MattFenwick 不确定。这几乎就像我们想要一个isEmptyMonoid/Alternative。或者一些让我们做一个“外部方程”的类型类,其中outereq :: f a -> f b -> Bool
【解决方案2】:

我有一个通用的解决方案,但它只适用于遵守left catch 法律的MonadPlus 实例(这可能只是必要条件,而不是充分条件):

isZero :: (MonadPlus m) => m a -> m Bool
isZero x = (x >> return False) `mplus` return True

switch :: (MonadPlus m) => m a -> m ()
switch x = isZero x >>= \r -> if r then return () else mzero

它也适用于STM

(对于列表,它总是返回[()],但我想说这个定义不适用于任何满足左分布的东西。)

无法为Applicatives 以这种方式定义它,因为switch 会检查isZero 的值,而应用程序无法做到这一点。 (并且,MonadPlus 实例满足左捕获规则 rarely satisfyApplicative 法律。)

无论如何,看看switch . (switch :: m () -> m ()) = id 是否适用于这个定义会很有趣。

【讨论】:

    【解决方案3】:

    我找到了一个完全不同的答案,那就是the LogicT monad transformer。它有lnot 定义为:

    lnot :: MonadLogic m => m a -> m ()
    

    反转逻辑计算。如果m 至少有一个值成功,则lnot m 失败。如果m 失败,则lnot m 将成功()

    我相信这正是您想要的。

    【讨论】:

    • 是的,看起来像。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2020-11-30
    • 2012-06-09
    • 2011-07-27
    • 2021-06-10
    • 2012-03-24
    • 2018-06-28
    • 2010-12-04
    相关资源
    最近更新 更多