3

所以在 scala 中,我们有典型的 Lens 签名:

case class Lens[O,V](get: O => V, set: (O,V) => O)

但正如您所看到的,它只更新和设置相同类型的值,它不会为另一种类型设置一种类型。我想到的是更像这样的东西:

case class Lens[O[_],A,B](get: O[A] => A, set: (O[A],B) => O[B])

对我A的问题是B有意义的。O[_]这是否不再是同构的?有没有更简单的方法而不违反一些规则?

4

2 回答 2

1

我认为要找出正确的Lens抽象,记住一个具体的可镜头类型会很有帮助。

但是,对于您的特定示例,我们可以说:

case class Lens[O[_],V[_],A,B](get: O[A] => V[A], set: (O[A],V[B]) => O[B])

我不认为这种镜头可以组成。为了组成镜头,a 的结果get必须能够输入set. 但是在这里, a 的结果get是 a V[_],而set需要 a O[_]

作为进一步的解释,这是另一种可能的多态镜头,但它可能不适合您的需求:

trait Lens[T[_]] {
  def get[A](t: T[A]): A
  def set[A,B](t: T[A], x: B): T[B]
}

它可以像这样组成:

def composeLenses[T[_],U[_]](lens1: Lens[T], lens2: Lens[U]) = 
  new Lens[({type x[A] = T[U[A]]})#x] {
    def get[A](t: T[U[A]]): A = lens2.get(lens1.get(t))
    def set[A,B](t: T[U[A]], x: B): T[U[B]] = lens1.set(t, lens2.set(lens1.get(t), x))
  }

我无法Lens抽象地找出定义 - 为了做到这一点,我必须使用这个具体案例:

case class Box[A](x: A)

def boxBoxGet[A](b: Box[Box[A]]): A = ???
def boxBoxSet[A,B](b: Box[Box[A]], x: B): Box[Box[B]] = ???
于 2015-07-02T00:58:45.450 回答
1

在 haskell lensmonocle中,多态镜头有 4 个类型参数。它们等效于以下实现:

case class PLens[S, T, A, B](get: S => A, set: B => S => T)

那么单色镜片只是一个类型别名:

type Lens[S, A] = PLens[S, S, A, A]

您可以将 4 个类型参数解读为:如果我在 S 中将 A 更改为 B,那么我会得到一个 T。

例如

S = (Int, String)
T = (Long, String)
A = Int
B = Long
于 2015-07-17T11:11:10.180 回答