2

我习惯于使用a <> bwhereabtake 参数。

> 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 ‘&lt;|>’
    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
4

1 回答 1

5

我们想表达类似“如果结果类型是Alternative,那么返回该类型的函数Alternative也是”。然而,这是不对的,因为只有* -> *类型可以是Alternative.

我们可能会尝试通过说结果类型应该是f afor some来解决我们的问题Alternative f,但这仍然不好,因为我们要为其定义实例的类型也必须具有 kind * -> *

实际上,我们只想为and someAlternative的组合定义一个实例。我们可以将这个概念稍微概括为以下几点:((->) r)Alternative f

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

不幸的是,库中已经有一个不同的Alternative 实例,它与上面的实例发生冲突。Compose f gtransformers

或者,我们可以注意到这与(模包装)ReaderT r m相同,幸运的是,正确的实例已经通过以下方式导出:Compose ((->) r) mnewtypetransformers

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
于 2015-04-03T14:24:54.013 回答