重复fmap的乐趣

ham*_*mar 54 haskell functor

我在玩弄玩家,我发现了一些有趣的东西:

平凡的,id可以在类型中实例化(a -> b) -> a -> b.

使用我们拥有的列表仿函数fmap :: (a -> b) -> [a] -> [b],它与之相同map.

((->) r)函子(from 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)
Run Code Online (Sandbox Code Playgroud)

这种模式会继续吗?为什么/为什么不呢?是否有一个公式表示fmap我需要在n次嵌套列表上映射函数的数量?

我尝试编写一个测试脚本来搜索n = 4的解决方案,但GHC在40 fmap秒左右开始吃太多内存.

Dan*_*her 37

我无法解释为什么,但这是周期的证明:

假设k >= 2fmap^(4k) :: (a -> b) -> F1 F2 F3 a -> F1 F2 F3 b,其中Fx代表未知数/任意Functor.fmap^n代表fmap应用于n-1 fmaps,而不是n重复迭代.感应开始可以通过手工验证或查询ghci.

fmap^(4k+1) = fmap^(4k) fmap
fmap :: (x -> y) -> F4 x -> F4 y
Run Code Online (Sandbox Code Playgroud)

统一用- >乙产量a = x -> y,b = F4 x -> F4 y,所以

fmap^(4k+1) :: F1 F2 F3 (x -> y) -> F1 F2 F3 (F4 x -> F4 y)
Run Code Online (Sandbox Code Playgroud)

现在,fmap^(4k+2)我们必须统一F1 F2 F3 (x -> y)使用(a -> b) -> F5 a -> F5 b.
因此F1 = (->) (a -> b),F2 F3 (x -> y)必须与之统一F5 a -> F5 b.
因此F2 = (->) (F5 a)F3 (x -> y) = F5 b,即F5 = F3b = x -> y.结果是

fmap^(4k+2) :: F1 F2 F3 (F4 x -> F4 y)
             = (a -> (x -> y)) -> F3 a -> F3 (F4 x -> F4 y)
Run Code Online (Sandbox Code Playgroud)

对于fmap^(4k+3),我们必须统一a -> (x -> y)使用(m -> n) -> F6 m -> F6 n),给予a = m -> n,
x = F6 my = F6 n,因此

fmap^(4k+3) :: F3 a -> F3 (F4 x -> F4 y)
             = F3 (m -> n) -> F3 (F4 F6 m -> F4 F6 n)
Run Code Online (Sandbox Code Playgroud)

最后,我们必须统一F3 (m -> n)使用(a -> b) -> F7 a -> F7 b,所以F3 = (->) (a -> b),m = F7 an = F7 b,因此

fmap^(4k+4) :: F3 (F4 F6 m -> F4 F6 n)
             = (a -> b) -> (F4 F6 F7 a -> F4 F6 F7 b)
Run Code Online (Sandbox Code Playgroud)

并且循环完成.当然,结果来自于查询ghci,但也许推导可以解释它是如何工作的.