【问题标题】:map Functor over a list in Haskell在 Haskell 中的列表上映射 Functor
【发布时间】:2018-11-01 15:22:11
【问题描述】:

有点困惑。 fmap 听起来它可以在map 的所有Maybe 列表中使用,但如果我使用例如,我无法让它工作。 fApplyFunctor = (+1) <$> [Just 1, Just 2]

似乎工作得很好的是:map ((+1) <$>) [Just 1, Just 2, Just 3]。从这个意义上说,这似乎有点矫枉过正,我记得fmap 可以自己做到这一点......

【问题讨论】:

  • 定义(<<$>>) = fmap . fmap,然后使用(+1) <<$>> [Just 1, Just 2, Just 3]。另外,(<<<$>>>) = fmap . fmap . fmap 代表 (+1) <<<$>>> Right [Just 1, Just 2, Just 3] 等。

标签: haskell functor map-function


【解决方案1】:

没有fmap 意味着您可以映射 任意Functor 类型(现在可以将其视为一个集合),但您只能这样做一个“函子级别” 深。如果你 fmap 带有一个列表,它完全等同于 map

fmap 但是在各种Functors 上定义,例如列表、Maybes 等。因此,您可以在此将fmap 中的fmap 映射到两个 级别:

fApplyFunctor = <b>fmap (fmap (+1))</b> [Just 1, Just 2]

这将导致:

Prelude> fmap (fmap (+1)) [Just 1, Just 2]
[Just 2,Just 3]
Prelude> (fmap (+1)) <$> [Just 1, Just 2]
[Just 2,Just 3]
Prelude> ((+1) <$>) <$> [Just 1, Just 2]
[Just 2,Just 3]

编辑:就像@DanielWagner 说的那样,存在一个数据类型Compose 可以在两个Functors 上工作(或者更多,如果你级联),因此允许我们fmap 两层深。这是这样实现的:

newtype Compose f g a = Compose { getCompose :: f (g a) }

instance (Functor f, Functor g) => Functor (Compose f g) where
    fmap f (Compose x) = Compose (fmap (fmap f) x)

所以在这里我们再次在两个级别上执行fmap

Prelude Data.Functor.Compose> getCompose ((+1) <$> Compose [Just 1, Just 2])
[Just 2,Just 3]

但正如您所见,它需要一些语法来首先将数据包装在 Compose 中,然后再将其从 Compose 中“解包”出来,因此这也需要一些额外的工作。

【讨论】:

  • 还有(+1) &lt;$&gt; Compose [Just 1, Just 2]。但是在我遇到的每一个真实案例中,引入Compose 比只输入两次fmap 在语法上要重得多,所以... +1 来自我的这个答案。 =)
  • @DanielWagner:谢谢。不知道Compose,添加到答案中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-27
  • 1970-01-01
  • 1970-01-01
  • 2016-07-31
  • 2019-10-12
相关资源
最近更新 更多