1

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.

Pavel
  • 127
  • 6

2 Answers2

2

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

Julien Truffaut
  • 477
  • 4
  • 10
-1

Look at Shapless lenses or at scalaz as @Peter commented.

roterl
  • 1,883
  • 14
  • 24
  • 1
    This is pretty much a link only answer. Some descriptions or examples would make it better. Referencing a comment isn't useful since comments shouldn't answer questions, and it could be removed at any time. If you think it's useful, bring that information into your answer – Daenyth Dec 14 '14 at 02:11