How can I get the self value from within the implementation of an interface function?

G-d willing

Hello,

I will make this question simple using the following code (I am using the default Asset template when doing daml new <project name)

data ViewType = ViewType
  with
    owner : Party
    name : Text

interface IAsset
  where
  viewtype ViewType

  doSomething : Bool -> Update (ContractId IAsset)

  choice DoSomething: ContractId IAsset
    controller (view this).owner
      do
        doSomething this True

Now, I want to use this interface inside the Asset template.
So I added the following code to the template:

template Asset
  with
    issuer : Party
    owner  : Party
    name   : Text
  where
    ensure name /= ""
    signatory issuer
    observer owner

    interface instance IAsset
      for Asset where

      view = ViewType with ..

      doSomething value = do
        if value then create this with name = "test"
            else return self

And I getting an error saying that self is not recognized.
So, it does not help using toInterfaceContractId @IAsset self cause self is not recognized.
How can this be solved? And why self is not recognized?

Thanks

According to the Daml language reference documentation on templates, self implicit local binding is only in scope in choices. In your example you can get the interface ContractId using the self implicit local binding inside the DoSomething choice and pass it as a parameter to the doSomething method.

interface IAsset
  where
  viewtype ViewType

  doSomething : (ContractId IAsset) -> Bool -> Update (ContractId IAsset)

  choice DoSomething: ContractId IAsset
    controller (view this).owner
      do
        doSomething this self True

then the doSomething method can be implemented as

doSomething iassetCid value = do
  if value 
  then toInterfaceContractId @IAsset <$> create this with name = "test"
  else return iassetCid
1 Like

The reason for that is that you can all an interface method even if there is no actual contract behind it and therefore also no contract id.

2 Likes

G-d willing

That’s interesting.
And how do you do that? calling a method of an interface even if there is no actual contract behind it?

Here is a simple example:

module Main where

import DA.Assert
import Daml.Script

template T
  with
    p : Party
  where
    signatory p

    interface instance I for T where
      view = IView
      f = "foobar"

interface I where
  f : Text
  viewtype IView

data IView = IView {}
  deriving (Show, Eq)

test = script do
  p <- allocateParty "p"
  -- Note that we are just creating the template value here, we are not calling `create`
  -- so there is no contract.
  let templateValue : T = T p
  let interfaceValue : I = toInterface templateValue
  f interfaceValue === "foobar"
1 Like