函子的目的
The purpose of functors
我正在尝试理解仿函数并且理解其概念但不理解其目的?
考虑以下示例:
val list1 = List(1,2,3)
val list2 = Functor[List].map(list1)(_ * 2)
好处是什么:
list1.map(x => x * 2)
?
目的不一定是Functor[List].map(list1)(_ * 2)
而是:
def timesTwo[F[_]: Functor](f: F[Int]) =
Functor[F].map(f)(_ * 2)
对可以映射的一切进行抽象的能力。
仿函数是一种类型 class,它抽象了所有可以进行的类似映射操作的类型。这样我们就可以统一操作这些类型的实例了。
我认为看一下仿函数的 map 函数的类型签名很有用
map :: (a -> b) -> Functor a -> Functor b
这为我们提供了一种将值放入容器 (Functor) 并使用普通函数(使用 map)对该值进行操作的方法,所有这些都无需从容器中取出值。
然后可以将 Functor 视为高阶类型;也就是说,它是一个包含另一个值的值,但是有一个统一的接口来与之交互——这个接口给了函子一种独特的表达形式,使它们特别适合某些问题
仿函数是类型构造函数F[_]
和函数
def fmap[A,B](f: A => B): F[A] => F[B]
(这与 cats
中的写法不同,但它实现相同并且可以互换)
那么这是什么意思呢?
类型构造函数基本上是类型之间的映射你给它一个类型 A
,它给你一个结果类型 F[A]
.
您拥有函数 fmap
的事实意味着以下内容:每次您能够从 A
转到 F[A]
时,您可以从 F[A]
转到 F[B]
B
.
法律
每个函子都必须遵守这些恒等式
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)
我正在尝试理解仿函数并且理解其概念但不理解其目的?
考虑以下示例:
val list1 = List(1,2,3)
val list2 = Functor[List].map(list1)(_ * 2)
好处是什么:
list1.map(x => x * 2)
?
目的不一定是Functor[List].map(list1)(_ * 2)
而是:
def timesTwo[F[_]: Functor](f: F[Int]) =
Functor[F].map(f)(_ * 2)
对可以映射的一切进行抽象的能力。
仿函数是一种类型 class,它抽象了所有可以进行的类似映射操作的类型。这样我们就可以统一操作这些类型的实例了。
我认为看一下仿函数的 map 函数的类型签名很有用
map :: (a -> b) -> Functor a -> Functor b
这为我们提供了一种将值放入容器 (Functor) 并使用普通函数(使用 map)对该值进行操作的方法,所有这些都无需从容器中取出值。
然后可以将 Functor 视为高阶类型;也就是说,它是一个包含另一个值的值,但是有一个统一的接口来与之交互——这个接口给了函子一种独特的表达形式,使它们特别适合某些问题
仿函数是类型构造函数F[_]
和函数
def fmap[A,B](f: A => B): F[A] => F[B]
(这与 cats
中的写法不同,但它实现相同并且可以互换)
那么这是什么意思呢?
类型构造函数基本上是类型之间的映射你给它一个类型 A
,它给你一个结果类型 F[A]
.
您拥有函数 fmap
的事实意味着以下内容:每次您能够从 A
转到 F[A]
时,您可以从 F[A]
转到 F[B]
B
.
法律
每个函子都必须遵守这些恒等式
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)