如何在 daml 合约映射值中使用合并?

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

难以理解语法,请提供声明此映射值合并的示例,并提供简要说明如何使用简单示例构建它

如果您有两个键类型相同的地图

m1 : Map k a
m2 : Map k b

您可以将它们合并成一个地图 Map k c 调用 merge 像这样:

merge f1 f2 f12 m1 m2

哪里

  • f1 : k -> a -> Optional c 指定在 m1 但不在 m2 中找到密钥时要执行的操作。这里 f1 传递了密钥及其在 m1.
  • 中的对应值
  • f2 : k -> b -> Optional c 指定在 m2 但不在 m1 中找到密钥时要执行的操作。这里 f2 传递了密钥及其在 m2.
  • 中的对应值
  • f12 : k -> a -> b -> Optional c 指定在 m1m2 中都找到密钥时要执行的操作。这里f12传递的是key,它对应的值在m1,它对应的值在m2.

在每种情况下,return None 是您希望结果映射中缺少密钥。 Return Some x 如果您希望键存在并关联到值 x.

确保您已阅读 docs 函数。

merge 接受三个函数和两个映射。这两个映射具有相同的键类型,但值类型不同。映射结果形式 merge 必须有一个单一的值类型,当然,所以我们必须告诉合并如果

做什么
  1. 第一个提供的映射中只有一个值存在
  2. 仅存在第二个提供的地图的值
  3. 两个值都存在

例如,假设我们有一张地图 Map Int Text 和一张地图 Map Int Bool 我们想要合并,我们只说生成的地图应该表明我们属于上述三种情况中的哪一种.我们可以为此定义一个类型:

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

使用脚本尝试整个过程:

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)