Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/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中的Redux中创建类似于组合减速机的东西,当每个函数控制其状态的一小部分,但无法找到一种优雅的方式使其类型安全。到目前为止,我有这样的东西,看起来一点也不好 sealed trait Event case class Create() extends Event case class Save() extends Event object Reducers { type IntState = Int type StringState = String def

我试图从Scala中的Redux中创建类似于
组合减速机的东西,当每个函数控制其状态的一小部分,但无法找到一种优雅的方式使其类型安全。到目前为止,我有这样的东西,看起来一点也不好

sealed trait Event

case class Create() extends Event
case class Save() extends Event

object Reducers {
  type IntState = Int
  type StringState = String

  def intReducer(e: Event, state: IntState): IntState = ???

  def stringReducer(e: Event, state: StringState): StringState = ???

  def combineReducers[E, S1, S2](f: (E, S1) => S1, g: (E, S2) => S2): (E, (S1, S2)) => (S1, S2) = {
    { (e: E, states: (S1, S2)) => (f(e, states._1), g(e, states._2)) }
  }

  def combineReducers2[E, S1, S2, S3](f: (E, (S1, S2)) => (S1, S2), g: (E, S3) => S3): (E, (S1, S2, S3)) => (S1, S2, S3) = ???
}
似乎不成形记录是一个很好的选择,尽管对于类型繁重的编程来说是个新手,我不能按照下面的思路(或者可能需要一个带标签的函数列表?)


好了,试着找出什么可能是正确的typeclass:D很有趣

import cats._
import cats.implicits._

sealed trait Event
case class Create() extends Event
case class Save() extends Event

type Reducer[A] = (Event, A) => A

val intReducer: Reducer[Int] = ???
val stringReducer: Reducer[String] = ???
val doubleReducer: Reducer[Double] = ???

implicit object ReducerIS extends InvariantSemigroupal[Reducer] {
  override def product[A, B](fa: Reducer[A], fb: Reducer[B]): Reducer[(A, B)] =
    (e: Event, ab:(A,B)) => (fa(e,ab._1), fb(e, ab._2))
  override def imap[A, B](fa: Reducer[A])(f: A => B)(g: B => A): Reducer[B] = (e, b) => f(fa(e, g(b)))
}

val combined: Reducer[(Int, String, Double)] = (intReducer, stringReducer, doubleReducer).tupled
我的
InvariantSemigroupal
的实现不是很干净,但实际上,类型迫使您贯穿始终,很难出错


.tuple
方法是cats的隐式方法,在本例中,
Reducer
需要隐式的
InvariantSemigroupal

向@erip问好。@erip我看不出状态单子在这里有什么用处。我的问题是状态的形状随着每个函数添加到reducer中而改变。1)没有两个状态——将它们组合成一个复合状态。2) 根据我的经验,使用原语作为状态很少有用。你至少要用ADT把它们包起来。将它与状态monad结合起来应该可以解决您的问题,除非我仍然有误解。@erip的目标是将任意数量的“reducer”函数与尽可能少的样板代码行结合起来。哦,我想我看到了问题:这些reducer是否会动态地向状态添加组件?例如,一个reducer可以添加用户名;一个减速机可以添加重力仪吗?国家的“形状”不是先验的吗?抱歉,如果这是错误的,我不熟悉redux。如果是这样的话,我不知道是否有必要用强类型系统来实现这一点。有无限多的类型,它们之间有无限多的映射方式。您介意看看更新的问题吗?我正在尝试找出一个类型签名,以使用无形状标记的HLists作为状态。我认为我的答案对您的原始问题是有效的,您可以为您的第二个问题提出一个新的so问题:)此外,我认为没有理由对您的问题使用HList,你可以用猫做你需要的事情,就像shownI应该问的那样(手头的实际任务),也就是组合任意数量的这样的函数。看见
import cats._
import cats.implicits._

sealed trait Event
case class Create() extends Event
case class Save() extends Event

type Reducer[A] = (Event, A) => A

val intReducer: Reducer[Int] = ???
val stringReducer: Reducer[String] = ???
val doubleReducer: Reducer[Double] = ???

implicit object ReducerIS extends InvariantSemigroupal[Reducer] {
  override def product[A, B](fa: Reducer[A], fb: Reducer[B]): Reducer[(A, B)] =
    (e: Event, ab:(A,B)) => (fa(e,ab._1), fb(e, ab._2))
  override def imap[A, B](fa: Reducer[A])(f: A => B)(g: B => A): Reducer[B] = (e, b) => f(fa(e, g(b)))
}

val combined: Reducer[(Int, String, Double)] = (intReducer, stringReducer, doubleReducer).tupled