【问题标题】:How many fmaps does it take?它需要多少个 fmap?
【发布时间】:2019-04-08 13:26:20
【问题描述】:

Daniel Wagner 的comment 让我想到了这个问题。让我们从过度简化开始。假设你有一个类型

data Foo a = Foo [a]

然后你可以写Functor实例

instance Functor Foo where
  fmap f (Foo l) = Foo (fmap f l)

你可以把右边改写为

Foo . fmap f $ l

认识到(->) afmap = (.),你可以写它

fmap Foo (fmap f) l

重复,你得到

fmap (fmap Foo) fmap f l

所以,最后,

fmap f (Foo l) =
  fmap fmap fmap Foo fmap f l

如果你选择一个稍微复杂一点的函子呢?

data Bar = Bar [Maybe a]

instance Functor Bar where
  fmap f (Bar l) = Bar (fmap (fmap f) l)

我开始手动操作,但它开始失控,所以我切换到自动。

infixl 9 :@
data Expr
  = BAR | F | L | FMap | Expr :@ Expr
  deriving (Show)

rewrite :: Expr -> Expr
rewrite (p :@ (q :@ r))
  = rewrite $ FMap :@ p :@ q :@ r
rewrite (p :@ q) = rewrite p :@ q
rewrite e = e

main = print $ rewrite $
  BAR :@ (FMap :@ (FMap :@ F) :@ L)

不幸的是,这似乎产生了非常巨大的结果。我什至无法在合理的时间内计算出树最左边的叶子。这到底是个多大的表情?随着更多仿函数的分层,它的增长速度有多快?

【问题讨论】:

    标签: haskell


    【解决方案1】:

    无限。以下术语循环您的重写器:

    FMap :@ ((FMap :@ (FMap :@ FMap)) :@ FMap)
    

    只需三个步骤,即:

    ((FMap :@ FMap) :@ (FMap :@ (FMap :@ FMap))) :@ FMap
    (((FMap :@ (FMap :@ FMap)) :@ FMap) :@ (FMap :@ FMap)) :@ FMap
    (((FMap :@ ((FMap :@ (FMap :@ FMap)) :@ FMap)) :@ FMap) :@ FMap) :@ FMap
    

    最后一个以原始术语为开头。 (最初的循环术语本身是在重写你的BAR :@ (FMap :@ (FMap :@ F) :@ L) 的六个步骤之后出现的。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-07
      • 2017-05-08
      • 2015-09-18
      • 2012-01-22
      • 1970-01-01
      • 1970-01-01
      • 2011-07-02
      相关资源
      最近更新 更多