【问题标题】:Scala case class with function parameters具有函数参数的 Scala 案例类
【发布时间】:2015-03-01 07:09:17
【问题描述】:

我正在使用此代码:

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 from:

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

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

这个场景和标准有点不同

case class Person(name: String)

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

【问题讨论】:

    标签: scala


    【解决方案1】:

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

    这里,产生新的原始状态S(和新的结果A)的函数被包装(参见return操作)到作为案例类实现的monad State。我们需要它在 monad 上定义 flatMap 操作(参见 bind)。

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

    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)并返回单子类型 State
    • State.apply(run: S => (A, S)) 函数采用普通函数并返回(提升到)单子容器 State,因此它是单子的“返回”运算符
    • State.flatMap[B](f: A => State[S, B]): State[S, B] 对应“绑定”操作符

    Case 类仅用于具有显式“返回”函数 (apply),而不是使用 new 运算符。

    【讨论】:

    • 非常感谢@dk14。这里已经很晚了,所以我明天会好好了解一下并投票。有趣的是,我正在观看Scalaz State Monad,它显示了这种确切的情况。用 18:40 的演讲者解释,语法是“接受一个 S 并返回一个 SB,提升到状态的 lambda”。
    • 在您的问题示例中,从普通类型提升到 monad(“返回”运算符)由 State.apply(run: S => (A, S)) 表示。顺便说一句,这是一个 2012 年的视频,现代 scalaz 不接受 State.apply 内的 S => (A, S) - 它只在 States.state(f: S => (S, A)) 方法中这样做,所以只有一个“返回”方法。
    猜你喜欢
    • 1970-01-01
    • 2011-11-09
    • 1970-01-01
    • 2016-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多