Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala函数映射是一种模式匹配或交互_Scala - Fatal编程技术网

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

Scala函数映射是一种模式匹配或交互,scala,Scala,我花了数周时间试图理解scala中“提升”背后的想法 最初,它来自与《Scala中的函数式编程》一书第4章相关的示例 然后我找到了下面的主题“” 所选答案指定: def map[B](f: A => B): Option[B] = this match (Let's considered this as (*) ) 所以,从上面的代码中,我假设函数“map”是从函数匹配中派生出来的。因此,“地图”背后的机制 是一种模式匹配,用于在“有”和“无”之间提供案例选择 然后,我使用Seq、Opt

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

最初,它来自与《Scala中的函数式编程》一书第4章相关的示例

然后我找到了下面的主题“”

所选答案指定:

def map[B](f: A => B): Option[B] = this match (Let's considered this as (*) )
所以,从上面的代码中,我假设函数“map”是从函数匹配中派生出来的。因此,“地图”背后的机制 是一种模式匹配,用于在“有”和“无”之间提供案例选择

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

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

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

从页面中,我们可以看到标准库
map()
方法的类型配置文件有点不同

def map[B](f: (A) => B): Seq[B]
因此,标准库
map()
是从
a
类型的元素集合过渡到同一集合的方法,但元素类型为
B
。(
A
B
可能是相同的类型。它们不需要不同。)

因此,是的,它将函数
f()
应用于每个元素
A
,以创建每个新元素
B
。函数
f()
可能在其代码中使用模式匹配,但它不必这样做

现在考虑<代码> .MAP(PROTLN)< /代码>。

a
的每个元素都被发送到
println
,后者返回
Unit
。因此,如果
a
List[Int]
,那么
a.map(println)
的结果是
List[Unit]
,这不是非常有用


当我们想要的只是将信息发送到StdOut的副作用时,我们使用
foreach()
,它不会创建新的集合:
a.foreach(println)
@Jwvh提供了一个更基于编程的答案,但我想深入一点

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

这也是为什么像“map”这样的函数会非常混乱的原因。从本质上讲,程序员被教导将映射等作为集合上的操作,而实际上,它们是随函子和自然变换而来的操作(在范畴论中通常称为fmap,也是Haskell)

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

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

让我们把这些看成是函子,这个定义将是这样的:

在(非常非常)短的时候,我们把类型看作是我们语言范畴中的对象。这些类型之间的函数(类型构造函数)是此类中类型之间的态射。这些转换的集合称为内函子(将我们从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也是一个列表。我只是提供了这个例子,因为它更容易理解。基本的定义是这样的

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

事实证明,Monad在核心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语句)。为什么? 为了满足恒等式定律,我们需要某种“基本情况”,一个单位对象,在许多情况下(比如列表),这些类型将是我们称之为产品或副产品的类型


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

功能
map
用于
选项
与模式匹配无关。引用链接中使用的
match/case
只是定义函数的众多方法之一。它可以用
if/else
来定义。事实上,Scala 2.13中就是这样定义的源代码:

如果您将
选项
视为一个el的“集合”
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 
 }  
sealed abstract class Option[+A] extends IterableOnce[A] with Product with Serializable {
  self =>
    ...
    final def map[B](f: A => B): Option[B] =
      if (isEmpty) None else Some(f(this.get))
    ...
  }
val f: Int => Int = _ + 1

List(42).map(f)
// res1: List[Int] = List(43)

List.empty[Int].map(f)
// res2: List[Int] = List()

Some(42).map(f)
// res3: Option[Int] = Some(43)

None.map(f)
// res4: Option[Int] = None