11

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

可能的实现:

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

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

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

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

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

4

3 回答 3

8
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
于 2012-10-30T20:38:20.440 回答
4

我有一个通用的解决方案,但它只能适用于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满足左接规则的实例很少满足 Applicative法律。)

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

于 2012-10-31T14:45:11.797 回答
3

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

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

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

我相信这正是你想要的。

于 2013-07-26T07:53:21.710 回答