多项式函子
有一组有用的类型组合器可以用较小的组合来构建大型组合。这些作为 Functor 的示例实例具有指导意义,它们也可用作泛型编程的技术,因为它们可用于表示一大类常见的仿函数。
身份仿函数
身份函子简单地包装了它的论点。它是来自 SKI 演算的 I 组合器的类型级实现。
newtype I a = I a
instance Functor I where
    fmap f (I x) = I (f x)
在 Data.Functor.Identity 模块中可以找到 I,名称为 Identity 。
恒定的算子
常量仿函数忽略其第二个参数,仅包含常量值。它是 const 的类型级模拟,是来自 SKI 演算的 K 组合子。
newtype K c a = K c
请注意,K c a 不包含任何 a 值; K () 与 Proxy 同构。这意味着 K 的 fmap 实现根本不做任何映射!
instance Functor (K c) where
    fmap _ (K c) = K c
K 也被称为 Const,来自 Data.Functor.Const 。
此示例中的其余仿函数将较小的仿函数组合成较大的仿函数。
Functor 产品
仿函数产品需要一对仿函数并将它们打包。它类似于一个元组,除了 (,) :: * -> * -> *在 types *上运行,(:*:) :: (* -> *) -> (* -> *) -> (* -> *) 在 functors * -> *上运行。
infixl 7 :*:
data (f :*: g) a = f a :*: g a
instance (Functor f, Functor g) => Functor (f :*: g) where
    fmap f (fx :*: gy) = fmap f fx :*: fmap f gy
这种类型可以在 Product 中的 Data.Functor.Product 模块中找到 。
Functor 副产品
就像:*:类似于 (,) 一样,:+:是 Either 的仿函数级模拟。
infixl 6 :+:
data (f :+: g) a = InL (f a) | InR (g a)
instance (Functor f, Functor g) => Functor (f :+: g) where
    fmap f (InL fx) = InL (fmap f fx)
    fmap f (InR gy) = InR (fmap f gy)
:+:可以在 Data.Functor.Sum 模块中找到名称 Sum 。
Functor 组成
最后,:.:就像一个类型级别的 (.),将一个仿函数输出并将其输入到另一个仿函数的输入中。
infixr 9 :.:
newtype (f :.: g) a = Cmp (f (g a))
instance (Functor f, Functor g) => Functor (f :.: g) where
    fmap f (Cmp fgx) = Cmp (fmap (fmap f) fgx)
Compose 型可以在 Data.Functor.Compose 中找到 
用于通用编程的多项式仿函数
I,K,:*:,:+:和:.:可以被认为是某类简单数据类型的构建块的工具包。当你将它与固定点组合时,该套件变得特别强大,因为使用这些组合器构建的数据类型是 Functor 的自动实例。你可以使用该工具包构建模板类型,使用 I 标记递归点,然后将其插入 Fix 以获得可与标准动物园递归方案一起使用的类型。
| 名称 | 作为数据类型 | 使用仿函数套件 | 
|---|---|---|
| 成对的值 | data Pair a = Pair a a | type Pair = I :*: I | 
| 两个二个网格 | type Grid a = Pair (Pair a) | type Grid = Pair :.: Pair | 
| 自然数 | data Nat = Zero | Succ Nat | type Nat = Fix (K () :+: I) | 
| 清单 | data List a = Nil | Cons a (List a) | type List a = Fix (K () :+: K a :*: I) | 
| 二叉树 | data Tree a = Leaf | Node (Tree a) a (Tree a) | type Tree a = Fix (K () :+: I :*: K a :*: I) | 
| 玫瑰树 | data Rose a = Rose a (List (Rose a)) | type Rose a = Fix (K a :*: List :.: I) | 
这种设计数据类型的工具包方法是通用编程库(如 generics-sop) 背后的理念。我们的想法是使用如上所示的工具包编写泛型操作,然后使用类型类将任意数据类型转换为其通用表示形式:
class Generic a where
    type Rep a  -- a generic representation built using a kit
    to::a -> Rep a
    from::Rep a -> a