2016-12-31 1 views
2

처음으로 단안경을 사용하려고합니다. 내가하고 싶은 것을, 표준 스칼라를 사용하여,monocle을 사용하여 중첩 된 맵과 scala의 다른 필드를 수정하는 방법

case class State(mem: Map[String, Int], pointer: Int) 

그리고 현재 수정 : 여기

케이스 클래스입니다

def add1 = (s: State) => s.copy(
    mem = s.mem.updated("a", s.mem("a") + 1), 
    pointer = s.pointer + 1 
) 

을 그리고 여기 단안경 내 구현

val mem = GenLens[State](_.mem) 
val pointer = GenLens[State](_.pointer) 
val add2 = (mem composeLens at("a")).modify(_.map(_ + 1)) andThen pointer.modify(_ + 1) 

불행히도 코드가 깨끗하지 않습니다.

  1. 더 간결한 방법이 있습니까?
  2. 매크로로 모든 상용구를 생성 할 수 있습니까?

은 [업데이트] 나는 연결자와 함께 왔어요

def combine[S, A, B](lsa : Lens[S, A], f: A => A, lsb: Lens[S, B], g: B => B) : S => S = { s => 
    val a = lsa.get(s) 
    val b = lsb.get(s) 
    val s2 = lsa.set(f(a)) 
    val s3 = lsb.set(g(b)) 
    s2(s3(s)) 
    } 

문제는 내가 아직 이

[갱신 2] 내가 청소했습니다

중간 쓸모 S.을 생산할 필요가있다 combinator에 대한 코드를 작성하십시오.

def mergeLens[S, A, B](lsa : Lens[S, A], lsb : Lens[S, B]) : Lens[S, (A, B)] = 
    Lens.apply[S, (A, B)](s => (lsa.get(s), lsb.get(s)))(t => (lsa.set(t._1) andThen lsb.set(t._2))) 

    def combine[S, A, B](lsa : Lens[S, A], f: A => A, lsb: Lens[S, B], g: B => B) : S => S = { 
    mergeLens(lsa, lsb).modify { case (a, b) => (f(a), g(b)) } 
    } 

답변

2

당신은 at 대신 index를 사용하여 약간 짧은 버전을 얻을 수 있습니다 :

(mem composeOptional index("a")).modify(_ + 1) andThen pointer.modify(_ + 1) 

그러나 mergeLens은 또한 Lens 법칙을 만족하지 않는 가로 조성으로 알려진 경우 동일한 필드에 두 Lenses 점 :

import monocle.macros.GenLens 

    case class Person(name: String, age: Int) 
    val age = GenLens[Person](_.age) 

    val age2 = mergeLens(age, age) 
    val john = Person("John", 25) 
    age2.get(age2.set((5, 10))(john)) != (5, 10) 
관련 문제