如何将失败的计算转换为成功的计算,反之亦然

时间:2012-10-30 20:18:39

标签: haskell typeclass

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

可能的实施:

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

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

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

解释是:给定一个成功的计算,使其失败;如果计算失败,请使其成功。我不确定,但这似乎可能与MonadPlus相反......如果你真的很眯眼。 ???

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

3 个答案:

答案 0 :(得分:7)

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

答案 1 :(得分:3)

我有一个通用解决方案,但它只适用于遵守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

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

无法以这种方式为Applicative s定义它,因为switch会检查isZero的值,而应用程序无法做到这一点。 (以及MonadPlus个符合左捕获规则rarely satisfy Applicative法律的实例。)

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

答案 2 :(得分:2)

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

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

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

我相信这正是你想要的。