自动函子实例

Automatic Functor Instance

给定以下代数类型:

ghci> data Foo a = Foo a

然后我实例化其中之一。

ghci> let f = Foo "foo"

最后,我想调用 fmap 来应用一个函数,(a -> b) -> Foo a -> Foo b

ghci> fmap (++ "bar") f

<interactive>:78:1:
    No instance for (Functor Foo) arising from a use of ‘fmap’
    In the expression: fmap (++ "bar") f
    In an equation for ‘it’: it = fmap (++ "bar") f

但是,由于我没有实现 FooFunctor 实例,所以我无法使用 fmap

有没有办法免费获得 Functor 个实例?我对 Haskell 的编译器知之甚少,但也许知道 Foo a 上的 fmap 只是将 (a -> b) 应用于 Fooa?

当然可以,将 deriving Functor 添加到您的数据声明并在文件顶部添加 {-# LANGUAGE DeriveFunctor #-}

在ghci工作,如果你念咒语

Prelude> :set -XDeriveFunctor

那么编译器将变得像您希望的那样聪明,即使不是那么热情。您将需要调用该功能,因此,

Prelude> data Foo a = Foo a deriving (Show, Functor)

Show 仅用于打印输出,如下所示)然后您将能够执行类似

的操作
Prelude> fmap (++"bar") (Foo "foo")
Foo "foobar"

在模块中,您可以通过添加 pragma

来实现相同的目的
{-# LANGUAGE DeriveFunctor #-}

module 声明之前。它至少对更直接的 Functor 实例有好处,但你可以将其愚弄成假阴性。

Prelude> data Boo a = Boo (Either a Bool) deriving Functor

<interactive>:9:43:
    Can't make a derived instance of ‘Functor Boo’:
      Constructor ‘Boo’ must use the type variable only as the
        last argument of a data type
      In the data declaration for ‘Boo’

同时

data Goo a = Goo (Either Bool a) deriving Functor

没问题,而且机器显然已经被黑客攻击,无法配对,因为

data Woo a = Woo (a, Bool) deriving Functor

是允许的。

所以它并没有那么聪明,但总比戳眼睛要好。