Reputation: 127
In haskell it is possible to do the following.
import Control.Lens
import qualified Data.Map as M
m :: Map Int (Map Int String)
m = M.empty & at 1 . non M.empty . at 2 .~ Just "one-two"
Is it possible to do something similar in scala? Maybe using scalaz? I mean updating nested map with default value.
Update: Ok can we at least compose function for updating value in a Map without specifying all involved types. Having function like this.
// modifyMap :: (k, v) -> (v -> v) -> Map k v -> Map k v
def modifyMap[K,V](k: K, v: V)(f: V => V)(m: Map[K,V]): Map[K,V] = {
m + (k -> f(m.getOrElse(k, v)))
}
And I would like to be able to compose this function, in what seems to be reasonable way.
// (modifyMap (1, M.empty) . modifyMap (2, "")) (const "one-two") M.empty
(modifyMap(1, Map.empty) compose modifyMap(2, ""))(_ => "one-two")(Map.empty)
It is basically the same as haskell example, but type just would not derive with out being fully specified.
Upvotes: 1
Views: 601
Reputation: 497
you can get something similar with Monocle :
import monocle.syntax._ // to use optics as infix operator, it is required to guide type inference
import monocle.function._ // to get generic optics like at, index etc
import monocle.std.map._ // to get Map instances of At, Index
(Map.empty[Int, Map[Int, String]] applyOptional index(1) composeLens at(2)).set(Some("one-two"))
// if you prefer there are some symbolic aliases
(Map.empty[Int, Map[Int, String]] &|-> index(1) ^|-> at(2)).set(Some("one-two"))
I couldn't test it, please tell me if it doesn't compile
Upvotes: 2