我试图了解仿函数并理解概念而不是它的目的?
请考虑以下示例:
val list1 = List(1,2,3)
val list2 = Functor[List].map(list1)(_ * 2)
有什么好处:
list1.map(x => x * 2)
答案 0 :(得分:7)
目的不一定是Functor[List].map(list1)(_ * 2)
,而是:
def timesTwo[F[_]: Functor](f: F[Int]) =
Functor[F].map(f)(_ * 2)
抽象可以映射的所有内容的能力。
答案 1 :(得分:4)
仿函数是一个类型构造函数F[_]
以及一个函数
def fmap[A,B](f: A => B): F[A] => F[B]
(这与cats
中的编写方式不同,但实现相同且可互换)
那是什么意思?
类型构造函数基本上是类型之间的映射。为它提供类型A
,它为您提供结果类型F[A]
。
您拥有fmap
功能的事实意味着以下内容:每次您从F[A]
转到{{F[B]
时,您都可以从A
转到B
1}}。
每个探子都必须遵守这些身份
fmap(identity[A]) == identity[F[A]]
fmap(a compose b) == fmap(a) compose fmap (b)
仿函数法则确保类型级函数(类型构造函数)和值级函数(A => B
和F[A] => F[B]
)能够很好地协同工作。
不的好处是您可以使用不同的语法编写一些函数。事实上,在您的示例中,Functor[List].map(list1)(_ * 2)
比简单地list1.map(_ * 2)
更难写。
好处是你可以编写适用于任何仿函数的函数。
这是一个例子
import cats.Functor
def foo[A,B,F[_]: Functor](fb: F[B], ab: A => B)(eab: Either[F[A],F[B]]): F[B] =
eab.fold(fa => Functor[F].map(fa)(ab),identity)
答案 2 :(得分:1)
仿函数是一种类型类,它抽象出可以制作的所有类型的类似地图操作。通过这样做,我们可以统一的方式操作这些类型的实例。
答案 3 :(得分:0)
我认为查看仿函数地图函数的类型签名是有用的
map :: (a -> b) -> Functor a -> Functor b
这为我们提供了一种方法,可以将值放在容器(Functor)中,并使用普通函数(使用map)对该值进行操作,而无需将值从容器中取出。
然后可以将Functor视为高阶类型;也就是说,它是一个包含另一个值的值,但是具有与之交互的统一界面 - 这个界面为仿函数提供了一种独特的表达形式,使它们特别适合某些问题