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

时间:2015-04-03 13:16:17

标签: haskell

我习惯使用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

1 个答案:

答案 0 :(得分:4)

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

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

实际上,我们只想为Alternative和某些((->) 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 g已经有了transformers instance个不同的版本,它与上述实例发生了冲突。

或者,我们可以注意到ReaderT r mCompose ((->) r) m(模newtype包装)相同,幸运的是,正确的实例已由transformers导出:< / p>

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