带有函数参数的Scala案例类

时间:2015-03-01 07:09:18

标签: scala

我正在使用此代码:

case class State[S, +A](run: S => (A, S)) {
  ...                                          
  def flatMap[B](f: A => State[S, B]): State[S, B] = State(s => {    
    val (a, s1) = run(s)
    f(a).run(s1)
  })
  ...                                        
}

这是从FP in Scala的§6开始处理纯粹功能状态的抽象。 run是一个函数参数,它接受一个状态并发出一个值的元组和一个新状态。

我的问题围绕本节中的s =>语法:

... B] = State(s => { ...

这似乎是使用State'构造函数'(即apply)来构建一个新的State对象。但s代表什么?它是一个'匿名'状态,代表任何国家实例吗?如果是这样,它与this有什么不同?或者s对应于run的输入参数,即S来自:

... (run: S => ....  

为什么我要使用构造函数进行函数定义?请注意,flatMap定义的最后一个符号是)而不是},即关闭State应用构造函数。

此方案与标准

略有不同
case class Person(name: String)

场景,所以我想我会问......

1 个答案:

答案 0 :(得分:10)

您的第二个假设是正确的,s对应于run函数的输入参数,即S,它表示通过链的实际状态。所以s => {...}只是类型S => (A, S)的lambda定义。 Scala中的Lambda和函数是first-class citizens(值),因此您可以将它们作为参数传递给另一个类型(包括一些monad)。

此处生成新原始状态S(以及新结果A)的函数被包装(请参阅return操作)到monad状态,该状态实现为case类。我们需要它来定义flatMap操作(参见bind)monad。

为了使传递函数更清楚地作为参数,可以将代码重写为:

case class State[S, +A](run: S => (A, S)) {
    def flatMap[B](f: A => State[S, B]): State[S, B] = {
        def newState(s: S) = {    
           val (a, s1) = run(s)
           f(a).run(s1)
        }
        State(newState _)
    }
}

所以,根据monad definition

  • State[S, +A]是一个类型构造函数,它接受两种普通类型(S和协变A)并返回monadic类型State
  • State.apply(run: S => (A, S))函数接受一个普通函数并返回(提升)monadic容器State,因此它是一个" return" monad的运营商
  • State.flatMap[B](f: A => State[S, B]): State[S, B]对应于" bind"操作

案例类仅用于显式"返回"函数(apply)而不是new运算符。