是否有实例 Alternative ((->) r)?
Is there instance Alternative ((->) r)?
我习惯于使用 a <> b
,其中 a
和 b
接受参数。
> 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 m
与 Compose ((->) 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
我习惯于使用 a <> b
,其中 a
和 b
接受参数。
> 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 m
与 Compose ((->) 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