arjun a
arjun a

Reputation: 161

how to use merge in daml contract map value?

MapKey k => (k -> a -> Optional c) -> (k -> b -> Optional c) -> (k -> a -> b -> Optional c) -> Map k a -> Map k b -> Map k c

difficult to understand syntax please provide example for declaring this merge for map values and also provide brief description how to construct it with simple examples

Upvotes: 0

Views: 164

Answers (2)

chi
chi

Reputation: 116139

If you have two maps with the same key type

m1 : Map k a
m2 : Map k b

You can merge them into a single map Map k c calling merge like this:

merge f1 f2 f12 m1 m2

where

  • f1 : k -> a -> Optional c specifies what to do if a key was found in m1 but not in m2. Here f1 is passed both the key and its corresponding value in m1.
  • f2 : k -> b -> Optional c specifies what to do if a key was found in m2 but not in m1. Here f2 is passed both the key and its corresponding value in m2.
  • f12 : k -> a -> b -> Optional c specifies what to do if a key was found in both m1 and m2. Here f12 is passed the key, its corresponding value in m1, and its corresponding value in m2.

In each case, return None is you want the key to be missing in the result map. Return Some x if you want the the key to be present and associated to value x.

Upvotes: 2

bame
bame

Reputation: 995

Make sure you have a read of the docs for the function.

merge takes three functions and two maps. The two maps have the same key type, but different value types. The map resulting form merge has to have a single value type, of course, so we have to tell merge what to do if

  1. Only a value in the first supplied map is present
  2. Only a value int he second supplied map is present
  3. Both values are present

Let's for example say we have a map Map Int Text and a map Map Int Bool which we want to merge, and let's just say the resulting map should indicate in which of the three cases above we are. We can define a type for that:

data EitherOrBoth a b
  = EOBLeft a
  | EOBRight b
  | EOBBoth (a, b)
    deriving (Eq, Show)

Now we can define functions to say "Stick a value in Left", "Stick a value in Right", and "Stick two values in a tuple" in merge:

mergeWithBoth : (MapKey k) => Map k a -> Map k b -> Map k (EitherOrBoth a b)
mergeWithBoth = merge (\k x -> Some (EOBLeft x)) (\k y -> Some (EOBRight y)) (\k x y -> Some (EOBBoth (x, y)))

Try the whole thing out using a script:

import Daml.Script
import DA.Next.Map (Map, MapKey, merge, fromList)

data EitherOrBoth a b
  = EOBLeft a
  | EOBRight b
  | EOBBoth (a, b)
    deriving (Eq, Show)

mergeWithBoth : (MapKey k) => Map k a -> Map k b -> Map k (EitherOrBoth a b)
mergeWithBoth = merge (\k x -> Some (EOBLeft x)) (\k y -> Some (EOBRight y)) (\k x y -> Some (EOBBoth (x, y)))

testMerge = script do
  let
    mapIntText : Map Int Text = fromList[(1, "Hello"), (2, "World")]
    mapIntDec : Map Int Bool  = fromList[(2, True), (3, False)]

  assert (mergeWithBoth mapIntText mapIntDec
    == fromList [(1, EOBLeft "Hello"),(2, EOBBoth ("World", True)), EOBRight False)])
  
  return (mergeWithBoth mapIntText mapIntDec)    

Upvotes: 2

Related Questions