Search code examples
haskelldaml

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


Solution

  • 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)