问题描述
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
指定如果在m1
和m2
中都找到了密钥,该怎么办。在这里f12
传递了密钥,在m1
中对应的值以及在m2
中对应的值。
在每种情况下,如果您希望键在结果图中丢失,则返回None
。如果您希望密钥出现并与值Some x
相关联,请返回x
。
确保您已阅读该功能的docs。
merge
具有三个功能和两个映射。这两个映射具有相同的键类型,但具有不同的值类型。当然,地图生成的表单merge
必须具有单个值类型,因此我们必须告诉merge如果...怎么办
- 仅在第一个提供的地图中存在一个值
- 仅存在提供第二张地图的值
- 两个值都存在
例如,假设我们有一个地图Map Int Text
和一个地图Map Int Bool
要合并,而我们只说生成的地图应指出我们在上述三种情况中的哪一种。我们可以为此定义一个类型
data EitherOrBoth a b
= EOBLeft a
| EOBRight b
| EOBBoth (a,b)
deriving (Eq,Show)
现在,我们可以定义函数,使其在合并中说“在Left中粘贴一个值”,“在Right中粘贴一个值”和“在一个元组中粘贴两个值”:
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,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"),EOBBoth ("World",True)),EOBRight False)])
return (mergeWithBoth mapIntText mapIntDec)