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