Functional programming scala中处理状态的不变方法

Functional programming scala中处理状态的不变方法,functional-programming,state,scalability,scalaz,unfiltered,Functional Programming,State,Scalability,Scalaz,Unfiltered,我只是在学习Scala的同时开始我的FP之旅 现在需要在未过滤的web应用程序中维护列表[String]。当向端点发送POST请求时,应该从文件更新列表。当GET请求发送到同一端点时,将使用该列表 现在,我试图避免使用var来保存列表。我知道有时我们必须使用var,但我很好奇,有没有一种优雅的方法来处理这个问题。我试过使用scalaz.State迭代器和Steam。但是我被卡住了,因为我不知道如何将当前的不变状态传递给下一个请求。有什么建议吗 def update = State( l =>

我只是在学习Scala的同时开始我的FP之旅

现在需要在未过滤的web应用程序中维护
列表[String]
。当向端点发送
POST
请求时,应该从文件更新列表。当GET请求发送到同一端点时,将使用该列表

现在,我试图避免使用
var
来保存列表。我知道有时我们必须使用var,但我很好奇,有没有一种优雅的方法来处理这个问题。我试过使用scalaz.State迭代器和Steam。但是我被卡住了,因为我不知道如何将当前的不变状态传递给下一个请求。有什么建议吗

def update = State( l => {
  retrieve(filepath) match {
    case Success(lines) => (lines.split("[,\n\r]").toVector.map (_.trim), true)
    case Failure(_) => {
      log.error(s"Cannot retrieve the file.")
      (l, false)
    }
  }
})

def isContained(message: String) = State(l => (l, l.exists(message.contains)))

/* assume the following get or post method will be invoked when GET or POST request is sent to the endpoint */

def post() = update(Vector.empty) // how can I pass the updated state to the get method

def get(msg: String): Boolean = isContained(msg)(???)._2

然后,我不知道如何将当前状态作为输入传递给下一次就诊,而不使用
var

没有免费午餐。如果要避免易变性并避免将状态存储在某处,则需要使用返回值

State
只不过是一个函数
a=>B
(出于某种目的,我将其简化了一点),其中
a
是初始状态,
B
是最终结果

因此,在您的情况下,模型将如下所示:

def post(newMessage: String, state: List[String]): List[String] = {
  newMessage :: state
}

def get(msg: String, state: List[String]): Boolean = {
  state.contains(msg)
}
正如您在这里看到的,您需要为每个
post
get
提供当前状态。POST只需从文件中添加一条新消息(将您的业务逻辑放在这里),并返回一个新状态。对于
get
,您需要提供当前状态,以便能够检索到所需的内容。 您可以这样重写它:

def post(newMessage: String): List[String] ⇒ List[String] = state ⇒ {
  newMessage :: state
}

def get(msg: String): List[String] ⇒ Boolean = 
  _.contains(msg)
请注意,post返回的正是
A⇒ A
(其中
A=List[String]

ScalaZ
State
为您提供了Monad,用于链接内部函数以便于理解,还提供了一些额外的便利(如
map
get
put
等)。但本质上,基本模型是相同的

此代码更精确地表示
状态
的功能:

  type YourListState = List[String] ⇒ List[String]

  def post(newMessage: String, state: YourListState): YourListState = li ⇒ {
    newMessage :: state(li)
  }

  def get(msg: String, state: YourListState): List[String] ⇒ Boolean = {
    state(_).contains(msg)
  }
这允许您组合状态并提供初始值,并在需要时“运行”它,而不确定您是否真的需要它