2015-07-01 56 views
2

的类型,因此在Scala中,我们有典型的镜头签名参数镜头:如何实现改变状态

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]) 

随着ABO[_]我的问题是有意义。这停止同构吗?有没有一个简单的方法,而不违反一些规则?

回答

1

我认为要找出正确的Lens抽象,考虑具体的镜头类型会有所帮助。

然而,你的具体的例子,有一些东西我们可以说:

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

我不认为这种镜头可以组成。为了组成镜片,get的结果必须能够输入set。但是在这里,get的结果是V[_],而set需要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]] = ??? 
0

在haskell lensmonocle中,多晶型透镜具有4种类型参数。它们等同于以下实现:

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

然后monomoprhic镜头仅仅是一个类型别名:

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

可以读取4类型参数:如果我改变A与B组S的内那么我得到一个T.

eg

S = (Int, String) 
T = (Long, String) 
A = Int 
B = Long