Functor如何有用?

Mic*_*ael 6 haskell functional-programming scala functor

我们知道任何F[_]具有map符合某些定律的方法的泛型类型都是算子.例如,List[_]Option[_],是和F[A] = Env => A算子.我只是想知道这个仿函数抽象是否有意义.

我如何使用它们是仿函数的事实?你能展示一个非平凡计算的例子,它会使用map并且实际上有用吗?

Lui*_*las 9

函数等概念的最大好处之一是,有一些通用结构允许您使用更简单的仿函数构建更复杂的类型,并保证这些复杂类型具有某些属性.当你像你一样孤立地考虑它们时,可以理解的是,函数看起来毫无意义,但是你学习和掌握的这些结构越多越有用.

一个更简单的例子是几种组合仿函数的方法也产生了一个仿函数; 例如,如果List[A]Option[A]是仿函数,那么:

  • 仿函数的组成: List[Option[A]]Option[List[A]]
  • 仿函数产品: (List[A], Option[A])
  • 仿函数的总和: Either[List[A], Option[A]]

我不知道在Scala中写出这个,但在Haskell中这样的事实转化为通用代码,如下例:

-- A generic type to represent the composition of any two functors
-- `f` and `g`.
newtype Compose f g a = Compose { getCompose :: f (g a) }

-- If `f` and `g` are functors, so is `Compose f g`.
instance (Functor f, Functor g) => Functor (Compose f g) where
  fmap f (Compose fga) = Compose (fmap (fmap f) fga)
Run Code Online (Sandbox Code Playgroud)

这是一个非常简单的例子,但是:

  • 它至少已经成为一种分析工具.一个很多人在实践中写入的数据类型,当你通过这个例子的镜头看看他们,练得产品,金额或简单的函子组成.因此,一旦理解了这些结构,就可以在编写复杂类型时自动"感知"它是一个仿函数,以及如何编写它的map()操作.
  • 更精细的例子具有相同的味道:
    • 我们有一个通用的结构,当用实现的类型实例化时保证某些契约Functor;
    • 当我们Functor向任何类型添加实现时,我们可以在该构造中使用该类型.

更详细的示例是免费monad(链接具有扩展的Scala示例),这是一种通用的解释器结构,它依赖于用户提供的Functors来定义语言的"指令".其他链接(这些链接大部分来自Google搜索):


dfe*_*uer 6

我不知道Scala,但在Haskell中,这个Functor类对于定义Van Laarhoven风格的镜头至关重要:

type Lens' s a = forall f . Functor f => (a -> f a) -> s -> f s
Run Code Online (Sandbox Code Playgroud)

这些镜头通常是针对特定相关类型s而定义的a,但它们的实用性必不可少,它们可以与任意仿函数一起使用.

Functor也是在其作为一个超类重要的作用ApplicativeTraversable.使用这些更强大的抽象时,达到该fmap方法通常非常有用.