Copying all fields from one contract to another
For upgrading DAR versions, I copy contracts created using the old version into contracts created using the new version. For the situation that the fields of the contracts didn’t change, I can do this without enumerating all the fields. For example, for a template C that exists unchanged in both versions 1 and 2, this works:
upgrade : C1 -> Update C2
upgrade c1@(C1 with ..) = do
let _ = c1
c2cid <- create C2 with
..
fetch c2cid
This I can use so:
(c1cid, c1) <- fetchByKey @C1 c1key
_ <- archive c1cid
c2 <- upgrade c1
This compiles alright and also executes.
However I would like to do this polymorphically. But this doesn’t compile:
class Upgrader c0 c1 where
upgrade : c0 -> Update c1
instance (Template c0, Template c1) => Upgrader c0 c1 where
upgrade a1@(c0 with ..) = do
let _ = a1
a2cid <- create c1 with
..
fetch a2cid
This results in the compiler error message
Source: parser
Severity: DsError
Message: error: You cannot use `..' in a record update
The error message is for the line upgrade a1@(c0 with ..) = do.
Can anyone explain what that means, and how to do it right?
Thanks a lot,
mesch.
Unfortunately, you cannot do that polymorphically. Record wildcards (that’s what the .. match is called) always have to match on a specific record.
What you could do is introduce a new typeclass that defines the conversion, implement that for all types you care about (for that you can use record wildcards) and then use that to do generic operations:
class Convertible a b where
convert : a -> b
instance Convertible C1 C2 where
convert (C1 with ..) = C2 with ..
instance (Template c0, Template c1, Convertible c0 c1) => Upgrader c0 c1 where
upgrade c0 = do
a2cid <- create @C1 (convert c0)
fetch a2cid
Thanks a lot, that confirms the suspicion I had. I just create all the instances then.
Thanks also for the proposed structure of the type classes; for the record, I had to make a few adjustments:
a2cid <- create @C1 (convert c0) with ..
caused the error
You cannot use `..' in a record update
Solved by dropping the with .. part.
instance (Template c0, Template c1, Convertible c0 c1) => Upgrader c0 c1 where
caused an error
The constraint ‘Converter c1 c2’
is no smaller than the instance head ‘Upgrader c1 c2’
(Use UndecidableInstances to permit this)
solved by adding
{-# LANGUAGE UndecidableInstances #-}
at the top.
Now,
instance (Template c0, Template c1, Convertible c0 c1) => Upgrader c0 c1 where
caused another error
Redundant constraint: Template c1
In the instance declaration for ‘Upgrader c1 c2’
Solved by dropping Template c1, .
With these adjustments, the code builds and runs.
Thanks again!
Cheers,
mesch.