Functor如何有用?

时间:2016-06-20 18:10:01

标签: scala haskell functional-programming functor

我们知道任何符合某些laws符合F[_]方法的通用类型map都是仿函数。例如,List[_]Option[_]F[A] = Env => A是仿函数。我只是想知道这个仿函数抽象是否有意义。

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

3 个答案:

答案 0 :(得分:9)

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

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

  • 仿函数的构成: Option[List[A]](List[A], Option[A])
  • 仿函数产品: Either[List[A], Option[A]]
  • 仿函数的总和: -- 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)

我不太了解在Scala中写出来,但在Haskell中,这些事实转化为通用代码,如下例所示:

map()

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

  • 至少它已经非常适合用作分析工具。人们在实践中编写的很多数据类型,当你通过这个例子的镜头看它们时,结果是更简单的仿函数的产品,总和或组合。所以,一旦你理解了这些结构,你就可以自动地感觉到#34;当你编写一个复杂的类型,它是一个仿函数,以及如何编写它的Functor操作。
  • 更精细的例子具有相同的味道:
    • 我们有一个通用构造,在使用实现Functor的类型实例化时保证某些合同;
    • 当我们向任何类型添加Functor实现时,我们可以在该构造中使用该类型。

更详细的示例是free monads(链接具有扩展的Scala示例),这是一种通用的解释器结构,它依赖于用户提供的using UnityEngine; using System.Collections; public class cursor : MonoBehaviour { Vector2 mouse; int w =32; int h=32; public Texture2D cursor1; // Use this for initialization void Start () { Cursor.visible = true; } // Update is called once per frame void Update () { mouse = new Vector2(Input.mousePosition.x, Screen.height - Input.mousePosition.y); } void OnMouseOver() { Cursor.SetCursor (cursor1, Vector2.zero, CursorMode.Auto); } void OnMouseExit() { Cursor.SetCursor (null,Vector2.zero,CursorMode.Auto); } } 来定义"指令"对于语言。其他链接(这些链接大部分来自Google搜索):

答案 1 :(得分:6)

我不知道Scala,但在Haskell中,Functor类对于定义Van Laarhoven-style lenses至关重要:

type Lens' s a = forall f . Functor f => (a -> f a) -> s -> f s

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

Functor作为ApplicativeTraversable的超类角色也很重要。使用这些更强大的抽象时,达到fmap方法通常非常有用。

答案 2 :(得分:1)

嗯,一旦你知道某个是Functor,你就不会得到map,你也可以获得所有可以用它衍生的函数

例如,可以以适用于任何仿函数的方式派生函数lift

升降机将提升"某个Functor A => B的{​​{1}}到F[A] => F[B]的函数,定义为

F[_]

如果您使用的是cats或scalaz等库,那么您可以免费获得这些功能。 cats documentation还有一些您可能感兴趣的其他示例