如何为具有两个参数的类型实例化“Functor”?

How can I instance `Functor` for a type with two parameters?

背景。 在我的一个 类 中,我们一直在探索 Parser monad。 Parser monad 通常定义为

newtype Parser a = Parser (String -> [(a, String)])

newtype Parser a = Parser (String -> Maybe (a, String))

无论哪种情况,我们都可以使用适用于这两种情况的代码将 Parser 实例化为 Functor

instance Functor Parser where
  fmap f (Parser p) = Parser (fmap applyF . p)
    where applyF (result, s) = (f result, s)

如果我们有 Parser 构建到 return Maybe (a, String),如果 result 存在,这会将 f 应用于 result。如果我们有一个 Parser 构建到 return [(a, String)],这将 f 应用于列表中 result 的每个 return。

我们可以实例化 ApplicativeMonadMonadPlusAlternative 是类似的通用方式(因此它们适用于 Maybe[]).

问题。如果我根据用于包装结果的类型参数化Parser,我如何为Functor和朋友实例化它?

newtype Parser m a = Parser (String -> m (a, String))

-- How do I instance `Parser` as a Functor if `m` is a Functor?

您可以在此处构造一个约束条件,即 m 也应该是 Functor 的一个实例类型,然后 fmap 该结果:

instance <b>Functor m</b> => Functor (Parser m) where
    fmap f (Parser p) = Parser (\x -> <b>fmap g</b> (p x))
        where <b>g</b> (r, s) = (f r, s)

因此,g 是一个对元组的第一个元素执行映射 f 的函数。因此,我们将 g 用作结果的 "mapping" 函数。

因此,这将适用于作为 Functor 实例的任何 m,例如 Maybe[]Tree 等.