【发布时间】:2012-02-02 22:51:22
【问题描述】:
我在玩仿函数,发现了一些有趣的东西:
简单地说,id 可以被实例化为 (a -> b) -> a -> b 类型。
使用列表函子我们有fmap :: (a -> b) -> [a] -> [b],它与map 相同。
对于((->) r)函子(来自Control.Monad.Instances),fmap是函数组合,所以我们可以实例化fmap fmap fmap :: (a -> b) -> [[a]] -> [[b]],相当于(map . map)。
有趣的是,fmap 八次给了我们(map . map . map)!
所以我们有
0: id = id
1: fmap = map
3: fmap fmap fmap = (map . map)
8: fmap fmap fmap fmap fmap fmap fmap fmap = (map . map . map)
这种模式会继续吗?为什么/为什么不?是否有一个公式来计算我需要将函数映射到 n 次嵌套列表上的 fmaps 数量?
我尝试编写一个测试脚本来寻找 n = 4 情况的解决方案,但 GHC 在大约 40 fmaps 时开始占用过多内存。
【问题讨论】:
-
它很快退化成一个循环或类似的东西,但我忘记了确切的公式。 (顺便说一句,lambdabot 实际上将
(.)定义为fmap。) -
@ehird:我认为你是对的。似乎
fmapn = 4k 次(对于 n 至少 8)给出了(map . map . map)。不过,我仍然很好奇为什么会发生这种情况。特别是因为实例发生了变化。 n = 8 时为(.) (.) (.) (.) (.) map map map,而n = 12 时为(.) (.) (.) (.) (.) (.) (.) (.) map (.) map map。