有什么情况可以/不能有数据类型的Functor实例?

时间:2017-04-25 08:51:04

标签: haskell typeclass functor category-theory

考虑具有种类的类型* - > *,我正在努力寻找规则并建立直觉,以便何时能够以及何时无法使用Functor。

到目前为止,我看到的规则如下:

  1. 对于具有限制的容器类型,没有Functor个实例 关于所包含的值。
  2. 示例:Functor您不能拥有Set个实例,因为包含的值需要Ord

    1. 逆变数据类型没有Functor个实例。
    2. 示例:

      newtype Contra a = Contra (a -> Int)
      

      除此之外,还有其他情况吗?

3 个答案:

答案 0 :(得分:5)

除了你的规则:

  • 必须是善意* -> *
  • 对包含值有限制的容器类型没有Functor实例。
  • 逆变数据类型没有Functor个实例。

我想补充一点:

  • "对于逆变类型的自然扩展":对于不变数据类型没有Functor实例。例如data Iso a b = Iso (a -> b) (b -> a)
  • GADT通常不能有Functor个实例。例如,

    data Foo a where
        Foo :: Foo Int
    

    也许你会以某种方式想把它归结为只有协变的"以某种方式规则(我不清楚这甚至有什么差异),或者#34;不受限制的容器类型"某种程度上的规则(GADT引入了非常类似约束的类型等式)。

但是,请注意,这些规则仅适用于Functor ,而不适用于一般的仿函数。我希望你能做的任何愚蠢的类型(适当类型)都会成为与Hask密切相关的一些合适类别的算符。

答案 1 :(得分:5)

从类别理论的角度来看,类似*->*的Haskell类型构造函数在Hask类别中定义了对象的映射(它是一个类别模数终止问题,我将方便地忽略)。仿函数是对象的映射,更重要的是,态射的映射。事实上,它主要是态射的映射 - 在某种程度上,对象的映射是其副作用。对象只是态射的终点。这种态射的映射必须保持构图和身份。

在Haskell中,态射是函数,函数的映射实现为fmap

在Haskell中,我们从对象的映射开始这一事实有点倒退。这是有效的,因为语言的语法极大地限制了定义对象映射的可能性。这种映射非常规则,并且通常配备有规范的函数映射。例如,代数数据类型是使用产品和副产品构建的,这些产品本质上是功能性的(因此自动deriving Functor的可能性)。此外,函数类型(分类指数)在第二个参数中是functorial(在第一个参数中是逆变量)。因此,只要我们使用bicartesian封闭类别(产品,副产品和指数)的工具,就可以轻松构建对象的函数映射。

必须为给定类别中的每个对象定义仿函数,因此受类型类约束的数据类型(例如,Set具有Ord约束)不是Functor s在Hask中,但它们可能是Hask子类别中的仿函数。 (可以在Haskell中使用自己的仿函数定义子类别。)

答案 2 :(得分:0)

Haskell用户指南中有-XDerivingFunctor个扩展名。您可以找到完整说明here。它描述了函子派生可能失败的所有情况。这种描述有算法检查正确类型等的情况。但我相信这个算法的约束列表是详尽无遗的。

例如,另一种情况,当类型具有种类 * -> *但不能是Functor的实例时:

  

数据类型的最后一个类型变量用于-XExistentialQuantification约束,或者在GADT中进行细化