Answers:
我想回答一个问题,以引起人们对八月的评论的关注:
这实际上不是怎么回事。发生的事情是,在Haskell 1.3中,地图的类型被概括为涵盖Functor。即,在Haskell 1.3中,fmap被称为map。然后在Haskell 1.4中还原了此更改,并引入了fmap。发生这种变化的原因是教学上的;在向初学者教授Haskell时,非常通用的地图类型使错误消息更加难以理解。我认为这不是解决问题的正确方法。
Haskell 98被某些Haskeller(包括我)视为倒退,以前的版本定义了一个更加抽象和一致的库。那好吧。
map and fmap
已经存在了很长时间-2006年8月在Haskell-prime邮件列表中重新加热-haskell.org/pipermail/haskell-prime/2006-August/thread.html。作为对策,我更喜欢现状。在我看来,Haskell的一个子集与Miranda大致对应似乎很有价值。在英国,Miranda被用作数学系学生的教学语言,而不仅仅是计算机科学系的学生。如果那种利基尚未被非功能性语言(例如Mathematica)所迷失,那么我看不到Haskell具有统一的功能map
。
引用https://wiki.haskell.org/Typeclassopedia#Functor中的Functor
文档
您可能会问为什么我们需要一个单独的
map
功能。为什么不取消当前的仅列表map
功能, 而是重命名fmap
为map
?好吧,这是一个好问题。通常的论点是,刚学习Haskell的人使用map
不正确时,宁愿看到关于list的错误而不是aboutFunctor
。
它们在应用程序站点上看起来相同,但是它们是不同的。当您将这两个函数map
或fmap
应用于值列表时,它们将产生相同的结果,但这并不意味着它们具有相同的用途。
运行GHCI会话(Glasgow Haskell编译器交互式)以查询有关这两个函数的信息,然后查看它们的实现,您会发现很多差异。
查询GHCI以获取有关的信息 map
Prelude> :info map
map :: (a -> b) -> [a] -> [b] -- Defined in ‘GHC.Base’
并且您将看到它被定义为适用于任何类型的值列表的高阶函数,a
从而产生任何类型的值的列表b
。尽管多态(上面的定义中的a
和b
表示任何类型),该map
函数都旨在应用于值列表,这只是Haskell中众多其他类型中的一种可能的数据类型。该map
函数不能应用于不是值列表的内容。
正如您可以从GHC.Base源代码中读取的那样,该map
函数实现如下
map _ [] = []
map f (x:xs) = f x : map f xs
它利用模式匹配将列表的头部(x
)从xs
列表的尾部()上拉下,然后使用:
(cons)值构造函数构造一个新列表,使其前置f x
(将其读为“应用于x的f”))到map
尾递归直到列表为空。值得注意的是,该map
函数的实现不依赖于任何其他函数,而仅依赖于自身。
现在尝试查询有关的信息fmap
,您将看到完全不同的东西。
Prelude> :info fmap
class Functor (f :: * -> *) where
fmap :: (a -> b) -> f a -> f b
...
-- Defined in ‘GHC.Base’
这次fmap
被定义为必须由那些希望属于Functor
类型类的数据类型提供其实现的功能之一。这意味着不仅可以使用“值列表”数据类型,而且可以提供一种以上fmap
功能的实现。这使得它fmap
适用于更大的数据类型集:函子确实!
正如您可以从GHC.Base源代码中读取的那样,该fmap
功能的可能实现是由Maybe
数据类型提供的:
instance Functor Maybe where
fmap _ Nothing = Nothing
fmap f (Just a) = Just (f a)
另一种可能的实现是2元组数据类型提供的实现
instance Functor ((,) a) where
fmap f (x,y) = (x, f y)
另一种可能的实现是列表数据类型提供的实现(当然!):
instance Functor [] where
fmap f xs = map f xs
这取决于map
功能。
该map
函数可以应用于值列表(其中值是任何类型),而该fmap
函数可以应用于更多数据类型:属于函子类的所有数据类型(例如,也许,元组,列表等)。 )。由于“值列表”数据类型也是一个函子(因为它提供了它的实现),因此fmap
可以应用于并产生与相同的结果map
。
map (+3) [1..5]
fmap (+3) (Just 15)
fmap (+3) (5, 7)