我可以避免这个基于替代函数的 Monad 约束吗?

问题描述 投票:0回答:1

我编写了以下函数(使用 这些 库):

import Control.Applicative (Alternative ((<|>)), optional)
import Data.These (These(..))

asumThese :: (Alternative f, Monad f) => f a -> f b -> f (These a b)
asumThese x y = optional x >>= \case
  Just x' -> maybe (This x') (These x') <$> optional y
  Nothing -> That <$> y

有没有办法可以删除

Monad
约束,或者没有办法摆脱使用绑定?

我的直觉告诉我我无法避免这里的

Monad
约束,但是任何人都可以告诉我为什么会这样吗?这样,将来我可以更好地了解我可能需要什么样的功能
Monad
以及哪些功能可以推广到
Applicative
和/或
Alternative

我感觉这与需要

Monad
进行排序有关,但我不能完全确定它,因为
f <$> x <*> y
以与
f <$> y <*> x
不同的顺序解析事物,所以
Applicative 中仍然有排序
.

parsing haskell monads applicative
1个回答
0
投票

当一个步骤的

action
取决于上一步的
return value
时,您需要 Monad m 而不是 Applicative m。控制对数据的依赖性被认为是捕捉“排序”的力量。如果你写
(,) <$> x <*> y
,那么
x
y
之前执行/解析/无论什么都只是一个约定。对于右边的
Applicative
y
可以在之前
x
发挥作用,或者
y
x
可以并行。在
x >>= maybe (return Nothing) (Just <$> y)
中,在
y
完成之前,不知道
x
是否会执行。对于
>>=
,排序是强制的,而不仅仅是常规的。

在这种情况下,控制确实依赖于数据:如果

optional x
返回
Nothing
,则下一个操作是运行
y
,但如果它返回
Just x'
,则下一个操作是
optional y
。也就是说,您只引入一个分支,以便在
y
成功时允许
x
失败。因此,我认为没有一种(好的)方法可以纯粹用
Alternative
来编写此操作。

当然还有最简单的

asumThese x y = (These <$> x <*> y) <|> This <$> x <|> That <$> y

但这 i) 以不同的顺序产生结果(即,它以不同的方式引入

Alternative
效果,因为效果不再依赖于数据)并且 ii) 效率低下。

© www.soinside.com 2019 - 2024. All rights reserved.