为什么只有Applicative需要`pure`而没有Functor?

时间:2015-10-30 16:57:18

标签: haskell functor category-theory

阅读this Wikibook about Haskell and Category Theory basics,我了解了Functors:

  

仿函数本质上是类别之间的转换,所以给定   类别C和D,仿函数F:C - > d

     

将C中的任何对象A映射到D中的F(A)。

     

映射态射f:A - > C中的B至F(f):F(A) - > D中的F(B)

......听起来很不错。后来提供了一个例子:

  

我们也有一个示例实例:

instance Functor Maybe where
  fmap f (Just x) = Just (f x)
  fmap _ Nothing  = Nothing
  

这里是关键部分:类型构造函数可能将任何类型T转换为a   新类型,也许T.此外,fmap限制​​为Maybe类型需要一个   功能a - > b到函数可能a - >也许b。但那就是它!我们'已经   定义了两个部分,将Hask中的对象转换为对象   另一个类别(在Maybe上定义的Maybe类型和函数)   类型),以及将Hask中的态射视为态射的东西   这个类别。所以也许是一个算子。

我理解fmap的定义是如何关键的。我很困惑"类型构造函数可能"提供了第一部分。我宁愿期待像pure这样的东西。

如果我做对了,Maybe宁愿将C映射到D。 (因此是类别级别的态射,这可能是Functor的要求)

我想你可以这样重写我的问题:是否有一个没有pure明显实现的Functor?

4 个答案:

答案 0 :(得分:13)

我认为你在类型和价值观之间感到困惑。以下是仿函数的定义:

  

C D categories。从 C D 仿函数 F 是一个映射:

     
      
  • 关联每个对象X∈C一个对象 F(X)∈D
  •   
  • 关联到每个态射 f:X→Y∈C一个态射 F(f):F(X)→F(Y)∈D这样以下条件成立:

         
        
    • F(id:X→X)= id:F(X)→F(X)每个对象X∈C
    •   
    • F(g∘f)= F(g)∘F(f)所有态射 f:X→Y g:Y→Z
    •   
  •   

一个类别由对象和对象之间的态射组成。

Haskell中的所有代码都是Haskell类别Hask的一部分。在 Hask

  1. 类型是对象。
  2. 函数是类型之间的态射。
  3. 因此,Haskell中的所有Functor实例都是从Hask到Hask的函子(即它们是endofunctors)。

    更严格地说,对于Haskell中的Functor的所有实例:

    1. C = Hask
    2. D = Hask
    3. 现在,每个仿函数 F 是一个与每个对象关联的映射X∈C一个对象 F(X)∈D。< / p>

      1. 请注意, X F(X)分别是 C D 的对象。
      2. 由于 C D 都是 Hask X F(X)< / em>是类型而不是值。
      3. 因此, F:类型→类型或在Haskell中f : * -> *
      4. 实际上,这正是Haskell中定义Functor类型的方式:

        class Functor (f : * -> *) where
            fmap :: (x -> y) -> (f x -> f y)
        

        在这里,fmap是仿函数的第二部分。它是从值到值的函数。但是,Functor本身是一个类型构造函数(即从类型到类型的映射)。这就是Maybe是一个仿函数,[]是仿函数的原因,但Maybe Int[Int]不是仿函数。

        请注意,pure不构成仿函数定义的第一部分,因为它是从 X 的实例到 F(X)的实例的映射(即它是从值到值的函数)。但是,我们需要从 X F(X)的映射(即从类型到类型的映射)。

答案 1 :(得分:4)

  

如果我做对了,Maybe宁愿将C映射到D。 (因此是类别级别的态射,这可能是Functor的要求)

不是真的,因为CD有类别,而不是Haskell类型。 Functor(即类型类的实例,而不是一般的仿函数)是从 Hask 类别(Haskell类型和函数的类别)到<的映射。 strong> Hask 本身;也就是说,CD在这种情况下都是 Hask 。 Wikibook章节在 Hask中的Functors 部分中提到了这一点。在您的示例中,Maybe类型构造函数通过将类型a Hask 中的对象)转换为类型Maybe a来提供映射的第一部分( Hask 中的另一个对象。

  

我想你可以这样重写我的问题:Functor是否有明显的pure实现?

一个例子是Functor(,) a对。 fmap很容易编写\f (x, y) -> (x, f y) - 但pure(<*>)要求对Monoid a约束,因为没有a否则,处理额外data = as.data.frame(list(YY = rep("1962",10), MM = rep("01",10), DD = rep("01",10), HH = c("00","01","02","03","04", "05","06","07","08","09"))) date = paste(data$YY,data$MM,data$DD,sep="-") data$dateTime = as.POSIXct(paste(date,data$HH,sep=" "),format="%Y-%m-%d %H") 值的方式。有关更多讨论和其他示例,请参阅Good examples of Not a Functor/Functor/Applicative/Monad?

答案 2 :(得分:2)

我说Applicative实例类型会成为Either的延伸(我只需拥有Bifunctor的实例就可以了,但是另一方面使用它作为Monad是方便的),并且(恕我直言)不适合类似的事情:

data ABC a = A a | B a | C a

A,B,C都是&#34;同样可以&#34;。由于pure没有明显的选择,因此根本不应提供。{1}}。但fmap仍然完全正常。

答案 3 :(得分:2)

类别Hask将类型作为对象和函数作为箭头,因此Functor实例提供的对象映射必须将类型映射到类型。

fmap将箭头(即地图函数a -> b)映射到函数f的函数f a -> f b。 Functor类型构造函数是对象的映射,即类型之间的映射。

例如,Maybe类型构造函数将类型t映射到类型Maybe t,例如StringMaybe String

相反,pure将某些基础类型的值映射到相应的应用类型的值,例如“abc”和(只是“abc”)分别是StringMaybe String的值。