Haskell 如何将失败的计算转换为成功的计算,反之亦然
这很可能是一个寻找问题的解决方案。。。如果是这样,我请求你的原谅 可能的实施:Haskell 如何将失败的计算转换为成功的计算,反之亦然,haskell,typeclass,alternative-functor,monadplus,Haskell,Typeclass,Alternative Functor,Monadplus,这很可能是一个寻找问题的解决方案。。。如果是这样,我请求你的原谅 可能的实施: class Switch' f where switch :: f a -> f () instance Switch' [] where switch [] = [()] switch (_:_) = [] instance Switch' Maybe where switch Nothing = Just () switch (Just _) = Nothing 这
class Switch' f where
switch :: f a -> f ()
instance Switch' [] where
switch [] = [()]
switch (_:_) = []
instance Switch' Maybe where
switch Nothing = Just ()
switch (Just _) = Nothing
这种解释是:如果计算成功,就让它失败;给出一个失败的计算,让它成为一个成功的。我不确定,但这似乎有点像MonadPlus的反面。。。如果你眯起眼睛真的很难
这个概念是否有标准的typeclass或其他实现?如果有的话,基础数学是什么样子的(例如,这是一个半群,一个循环,等等)
或
我有一个通用的解决方案,但它只能用于遵守法律的
MonadPlus
实例(这可能只是一个必要条件,而不是充分条件):
它对我也有用
(对于列表,它总是返回[()]
,但是,我要说的是,这个定义不适用于任何左分布。)
对于Applicative
s,不可能用这种方式定义它,因为开关
检查的值为零,而应用程序不能这样做。(以及,MonadPlus
满足左捕捉规则应用性
法则的实例。)
不管怎样,看看是否切换是很有趣的。(switch::m()->m())=id
适用于这个定义。我找到了一个完全不同的答案,那就是。它的定义是:
反转逻辑计算。如果m
至少有一个值成功,lnot
m
失败。如果m
失败,则lnot m
使值()
成功
我相信这正是你想要的。switch
几乎是二阶元素——它几乎是自反的,在switch.switch.switch
=switch.switch
中。它最终会生成重复的轨道(虽然“最终”是正确的词,但当提到等待1次迭代时,它听起来很长)<代码>开关。开关是幂等的。这就是我刚才想到的所有关于switch的数学问题。[()]
为什么返回才是正确的,而不是说,[(),()…]
?这是返回()
,就像另一个例子一样。@AndrewC也许规律是switch
专门化为m()->m()
的是一个例子。@PetrPudlák是的,我认为这是最好的表达方式。好电话。由于switch::switch m=>ma->m()
,我们知道switch x::m()
,所以我说的所有开关都会自动保持。非常整洁。此外,对合是一个比我使用的更好的术语。@MattFenwick我的错误,我已经纠正了它们。Eq
约束是不可原谅的,当我的数据结构包含函数或其他不可Eq
-的东西时,我该怎么办?@MattFenwick不确定。这几乎就像我们想要一个isEmpty
作为Monoid
/替代品。或者一些类型类,让我们做一个“外部Eq”,其中outereq::fa->fb->Bool
是的,看起来像这样。谢谢
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
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
lnot :: MonadLogic m => m a -> m ()