gpt4 book ai didi

Scala - 函数映射是模式匹配或交互

转载 作者:行者123 更新时间:2023-12-04 20:05:20 25 4
gpt4 key购买 nike

我花了几周的时间试图理解 scala 中“提升”背后的想法。

原来是《Scala 函数式编程》一书第 4 章相关的例子

然后我找到了下面的主题“How map work on Options in Scala?

所选答案指定:

def map[B](f: A => B): Option[B] = this match (Let's considered this as (*) )

因此,从上面的代码中,我假设函数“map”是从函数 match 派生的。因此,“ map ”背后的机制是一种模式匹配,提供 Some 和 None 之间的案例选择

然后,我通过使用 Seq、Option 和 Map 的函数映射创建了以下示例(让我们将以下示例视为 (**) )

Example 1: map for Seq
val xs = Seq(1, 2, 3)
xs.map(println)

Example 2: map for Option
val a:Option[Int] = Some(5)
a.map(println)
val b:Option[Int] = None
b.map(println)

Example 3: map for Map
val capitals = Map("France" -> "Paris", "Japan" -> "Tokyo")
capitals.map(println)

从 (*) 和 (**) 中,我无法知道“map”是模式匹配还是迭代,或者两者兼而有之。

感谢您帮助我理解这一点。

最佳答案

@Jwvh 提供了更多基于编程的答案,但我想更深入地挖掘。

我当然很感激你试图理解 Scala 中的事物是如何工作的,但是如果你真的想深入挖掘,恐怕你需要获得一些类别理论的基本知识,因为在 scala 中没有“提升背后的想法” ”但只是“提升背后的想法”

这也是为什么像“map”这样的函数会非常令人困惑。本质上,程序员被教导映射等作为对集合的操作,因为它们实际上是仿函数和自然变换附带的操作(这通常在类别理论和 Haskell 中称为 fmap)。

在我继续之前,简短的答案是,它是您给出的示例中的模式匹配,并且在其中某些中,两者都是。 Map 是专门针对情况定义的,唯一的条件是它保持功能性

注意:我不会对下面的每个术语进行定义,因为我需要写一本书来构建以下一些定义,欢迎感兴趣的读者自行研究。通过遵循这些类型,您应该能够获得一些基本的了解

让我们将它们视为仿函数,定义将类似于以下内容:

简而言之,我们将类型视为我们语言类别中的对象。这些类型之间的函数(类型构造函数)是该类别中类型之间的态射。这些转换的集合称为 E​​ndo-Functor(将我们从 Scala 类别中带回 Scala 类别)。仿函数必须有一个多态(实际上在范畴论中有一个完全不同的(额外)定义)映射函数,它将接受一些对象 A,通过某种类型构造函数将其转换为对象 B。

implicit val option: Functor[Option] = new Functor[Option] {
override def map[A,B](optA: Option[A])(f: (A) => B): Option[B] = optA match{
case Some(a) => Some(f(a))
case _ => None
}
}


implicit val seq: Functor[Seq[_]] = new Functor[Seq[_]] {
override def map[A,B](sA: Seq[A])(f: (A) => B): Seq[B] = sA match{
case a :: tail => Seq(f(a), map(tail)(f))
case Nil => Nil
}
}

正如您在第二种情况中所看到的,两者都有一点(更多的是递归而不是迭代,但仍然如此)。

现在,在互联网对我大发雷霆之前,我会说你不能在 Scala 中对 Seq 进行模式匹配。它在这里起作用是因为默认的 Seq 也是一个 List。我只是提供这个例子,因为它更容易理解。基本的定义与此类似。

现在请稍等。如果您查看这些类型,您会发现它们还定义了 flatMap。这意味着它们比普通仿函数更特别。他们是单子(monad)。因此,除了满足功能性之外,它们还遵守一元法则。

事实证明 Monad 在核心 scala 中有不同的含义,更多内容请参见:What exactly makes Option a monad in Scala?

但同样非常非常短,这意味着我们现在处于一个类别,其中前一个类别的内仿函数是对象,它们之间的映射是态射(自然变换),这稍微更准确,因为如果你考虑一下当你采用一个类型并对其进行转换时,你会采用(继承)它的所有内部类型构造函数(2单元或内部态射),你不仅会采用这种类型的唯一想法而没有它的函数。

implicit val optionMonad: Monad[Option] = new Monad[Option] {
override def flatMap[A, B](optA: Option[A])(f: (A) => Option[B]): Option[B] = optA match{
case Some(a) => f(a)
case _ => None
}

def pure[A](a: A): Option[A] = Some(a)

//You can define map using pure and flatmap

}

implicit val seqMonad: Monad[Seq[_]] = new Monad[Seq[_]] {
override def flatMap[A, B](sA: Seq[A])(f: (A) => Seq[B]): Seq[B] = sA match{
case x :: xs => f(a).append(flatMap(tail)(f))
case Nil => Nil
}
override def pure[A](a: A): Seq[A] = Seq(a)
//Same warning as above, also you can implement map with the above 2 funcs
}

您始终可以信赖的一件事是映射具有模式匹配(或某些 if 语句)。为什么?为了满足恒等法则,我们需要某种“基本情况”,一个单元对象,在许多情况下(例如列表)这些类型将是我们所说的产品或副产品。

希望这不会让您更加困惑。我希望我能深入了解这方面的每一个细节,但这只需要几页纸,我强烈建议进入类别以充分了解这些细节的来源。

关于Scala - 函数映射是模式匹配或交互,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58515409/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com