2015-07-01 90 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