首页 > 解决方案 > 如何为具有两个参数的类型实例化 `Functor`?

问题描述

背景。在我的一堂课上,我们一直在探索Parser单子。Parsermonad 通常被定义为

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)

如果我们有一个Parserbuild to return Maybe (a, String),这适用fresultif the resultexists。如果我们有一个Parser内置的 return [(a, String)],这适用于列表中返回的f每个results。

我们可以实例化Applicative, Monad, MonadPlus, 和Alternative类似的通用方式(以便它们适用于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?

标签: haskellfunctional-programmingtypeclassfunctorparameterized-types

解决方案


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

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

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

因此,这将适用于任何m实例Functor,例如 a Maybe、 a []、 aTree等。


推荐阅读