Disambiguate accessing to contract fields
I have a couple of templates that share a field name (in this case name)
template DivulgeableAsset
with
owner: Party
name: Text
where
signatory owner
-- choices...
template PrivateAsset
with
owner: Party
name: Text
where
signatory owner
-- choices...
Later, in DAML Script, I would like to retrieve contracts that instantiate these templates and extract their respective names. I do something like the following:
run : Script ()
run = do
owner <- fromSome $ partyFromText "owner"
divulgee <- fromSome $ partyFromText "divulgee"
-- expect the owner to see both the divulgeable...
divulgeableAssets <- query @DivulgeableAsset owner
assertEq ["first"] (map ((name : DivulgeableAsset -> Text) . snd) divulgeableAssets)
-- ... and the private asset
privateAssets <- query @PrivateAsset owner
assertEq ["second"] (map ((name : PrivateAsset -> Text) . snd) privateAssets)
Note that I explicitly hinted the compiler the type of the name function. If I don’t, I get the following error:
Ambiguous occurrence ‘name’
It could refer to
either the field ‘name’,
imported from ‘Main’ at /some/path/daml/Test.daml:13:1-11
(and originally defined
at /some/path/daml/Main.daml:47:5-8)
or the field ‘name’,
imported from ‘Main’ at /some/path/daml/Test.daml:13:1-11
(and originally defined
at /some/path/daml/Main.daml:34:5-8)
Is there a cleaner way to disambiguate between those two functions (or, in general, to extract those fields)?
The full project is available here.
You can use record-dot-syntax which will resolve the ambiguity automatically. So for your example, that would be something like the following
assertEq ["first"] (map (\(_, asset) -> asset.name) divulgeableAssetsSeenByOwner)
Is this pattern that dlint could potentially catch? @cocreature @shaynefletcher
In general no, HLint does not have enough information to judge whether something is a record field or not. You could probably make something that works as long as the record and the usage of the field are in the same module but I expect the implementation effort to be fairly high
I concur. It’s easy enough to locate constructions like name : DivulgeableAsset -> Text however the syntax alone does not carry enough “context” for DLint to classify it as a field selector (as @cocreature says, which would then induce a lot of “special case” implementation effort) so if it were to issue hints, they would be highly speculative and often likely false positives which would be annoying and consequently quickly get disabled. Actually, the sample @stefanobaghino-da provides is somewhat interesting in that he reached for selectors in the first instance over dot-syntax which I’d think might be considered as slightly unusual when programming DAML and probably a consequence of prior Haskell experience. In fact if DAML already had the long desired and highly anticipated NoFieldSelectors feature it wouldn’t have been an option 
I’d have to write a program to test this but I expect sections to work here too e.g. map ((.name) . snd) divulgeableAssetsSeenByOwner and wonder if inference succeeds if phrased that way? I guess here is another way to dodge the ambiguity : map (\(_, DivulgeableAsset {name}) -> name) divulgeableAssetsSeenByOwner
Using a section, i.e., (.name) . snd does work but at least to me that is significantly harder to read and understand than \(_, asset) -> asset.name so I would not recommend that option here. Of course there might be other examples where the section is useful.