这可能是一个寻求问题的解决方案......如果是这样,我请求你的放纵!
可能的实施:
class Switch' f where
switch :: f a -> f ()
instance Switch' [] where
switch [] = [()]
switch (_:_) = []
instance Switch' Maybe where
switch Nothing = Just ()
switch (Just _) = Nothing
解释是:给定一个成功的计算,使其失败;如果计算失败,请使其成功。我不确定,但这似乎可能与MonadPlus相反......如果你真的很眯眼。 ???
这个概念是否有标准类型类或其他实现?基础数学会是什么样的,如果有的话(即这是一个半群,一个循环等)?
答案 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
会继续值()
。
我相信这正是你想要的。