是否有实例 Alternative ((->) r)?

Is there instance Alternative ((->) r)?

我习惯于使用 a <> b,其中 ab 接受参数。

> const ["a"] <> const ["b"] $ True
["a","b"]

为什么也没有a <|> b

> const ["a"] <|> const ["b"] $ True

<interactive>:64:13:
    No instance for (Alternative ((->) Bool))
      arising from a use of ‘<|>’
    In the expression: const ["a"] <|> const ["b"]
    In the expression: const ["a"] <|> const ["b"] $ True
    In an equation for ‘it’: it = const ["a"] <|> const ["b"] $ True

我们想表达类似 "if the result type is Alternative, then a function returning that type is Alternative too" 的意思。然而,这是不对的,因为只有 * -> * 类型可以是 Alternative

我们可能会尝试通过说结果类型对于某些 Alternative f 应该是 f a 来解决我们的问题,但这仍然不好,因为我们想要定义的类型该实例还必须具有类型 * -> *

其实我们只是想为((->) r)和一些Alternative f的组合定义一个Alternative实例。我们可以将这个概念稍微概括为以下内容:

import Data.Functor.Compose

instance (Applicative f, Alternative g) => Alternative (Compose f g) where
  empty = Compose $ pure empty
  Compose a <|> Compose b = Compose $ liftA2 (<|>) a b

不幸的是,transformers 库中 Compose f g 已经有一个不同的 Alternative instance,它与上述实例冲突。

或者,我们可以注意到 ReaderT r mCompose ((->) r) m 相同(取模 newtype 换行),幸运的是 transformers 已经导出了正确的实例:

instance Alternative m => Alternative (ReaderT r m)

所以我们可以这样做:

import Control.Monad.Reader

runReaderT (lift ["a"] <|> lift ["b"]) True
-- ["a", "b"] 

runReaderT (empty <|> lift (Just 0)) True
-- Just 0