我想尝试Monocle库。 但我找不到基本语法的帮助资源。
总之,我需要具有光学Map[K,V] -> A
的光学V -> A
,我怎么能定义它?
假设我有一些
import monocle.macros.GenLens
case class DirState(opened: Boolean)
object DirState {
val opened = GenLens[DirState](_.opened)
}
type Path = List[String]
type StateStore = Map[Path, DirState]
接下来我会遇到需要简单StateStore => StateStore
的地方,所以我正在导入
import monocle._
import monocle.std._
import monocle.syntax._
import monocle.function._
首先尝试定义:
def setOpened(path: Path): StateStore => StateStore =
at(path) composeLens DirState.opened set true
到这里
含糊不清的隐含值:
atMap
中的方法trait MapInstances
输入[K, V]=> monocle.function.At[Map[K,V],K,V]
和方法atSet
类型为trait SetInstances
的{{1}} 匹配预期类型[A]=> monocle.function.At[Set[A],A,Unit]
尝试将我的定义更改为
monocle.function.At[S,Path,A]
立即行动:
类型不匹配;发现:
def setOpened(path: Path): StateStore => StateStore = index(path) composeLens DirState.opened set true
(扩展为)monocle.function.Index[Map[Path,Nothing],Path,Nothing]
需要:monocle.function.Index[Map[List[String],Nothing],List[String],Nothing]
(扩展为)monocle.function.Index[Map[Path,Nothing],Path,A]
注意:
monocle.function.Index[Map[List[String],Nothing],List[String],A]
,但Nothing <: A
在trait Index
类型中不变。你可能希望 将A
定义为A
。 (SLS 4.5)
答案 0 :(得分:8)
import monocle.function.index._
import monocle.std.map._
import monocle.syntax._
def setOpened(path: Path)(s: StateStore): StateStore =
(s applyOptional index(path) composeLens DirState.opened).set(true)
让我们看一下index
def index[S, I, A](i: I)(implicit ev: Index[S, I, A]): Optional[S, A] =
ev.index(i)
trait Index[S, I, A] {
def index(i: I): Optional[S, A]
}
因此index
召唤类型为Index
的类型Index[S, I, A]
的实例。
这允许index
使用Map
,List
,Vector
等等。
问题是scala编译器需要在S
的调用站点推断出3种类型:I
,A
和index
。 I
很简单,它是您传递给index
的参数的类型。但是,S
和A
仅在您致电set
时知道。
已创建apply
语法来指导此类方案的类型推断,基本上applyOptional
会捕获S
Map[Path, DirState]
。这为编译器提供了足够的信息来推断A =:= DirState
。
答案 1 :(得分:0)