结合两种状态转换功能的优雅方法?

时间:2018-10-09 10:41:53

标签: scala

我正在尝试从Scala的Redux中制作类似于combineReducers的东西,当时每个函数都控制着状态的一小部分,但是却找不到一种使它安全的优雅方法。到目前为止,我有这样的东西看起来一点也不好。

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) = ???
}

无形记录似乎是一个很好的选择,尽管它是重类型编程的新手,但我无法弄清楚接下来应该如何处理(或者应该使用带有标记的HList函数?)。 )

def combineReducers(fTag: String, f: (E,A) => A, gTag: String, g: (E,B) => B): (E, HList1) => HList2 = {
  { (e: E, state: HList3) =>
    (fTag ->> f(e, state(fTag)) :: (gTag ->> g(e, state(gTag)) :: HNil
  }
}

1 个答案:

答案 0 :(得分:1)

去那里,尝试找出正确的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的实现不是很干净,但是实际上类型会迫使您始终难以理解。

在猫中,.tupled方法是隐式的,在我们的情况下,InvariantSemigroupal需要隐式Reducer