Skip to content
Discussions/App Development/Obtaining datatype field dynamicallyForum ↗

Obtaining datatype field dynamically

App Development5 posts233 views2 likesLast activity Jan 2022
DA
David_MartinsOP
Jan 2022

Hello everyone,

I was testing the ability to generically retrieve a field from a datatype, where we don’t necessarily know any of the arguments, but still would want to show the name of the field we obtained. Is this something that’s possible, even if it doesn’t align to what I was testing?

test : forall a b c. (HasField a b c) => a -> b -> Script c
test field dataType = do
    debug field
    return $ getField @a dataType

Thanks in advance.

CO
cocreature
Jan 2022

In Daml’s typesystem a record of a given type always has a fixed set of fields.

If you want to represent something with a varrying number of fields you can use something like a Map Text <yourvaluetypehere>.

DA
David_Martins
Jan 2022

Right, I guess the point of that test function was more to review the possibility of debugging the name of a data type field while also calling it as a symbol for the getField function.
At the end of the day, what I’d like the result to be, could be something like so, without using variables:

test : (HasField "myField" b c, Show c) => b -> Script c
test dataType = script do
    let var = getField @"myField" dataType
    debug $ "myField:" <> show var
    return var

Thank you.

CO
cocreature
Jan 2022

You cannot do this directly with HasField but you can define your own typeclass which gives you the field name at the value level. You then also have to define your own instances but depending on how frequently you use this, the boilerplate may be worth it:

{-# LANGUAGE AllowAmbiguousTypes #-}
module Main where

import DA.Record
import Daml.Script

data X = X { f : Text, g : Int }

class HasField a b c => HasField' a b c where
  fieldName : Text

instance HasField' "f" X Text where
  fieldName = "f"

instance HasField' "g" X Int where
  fieldName = "g"

debugField : forall f b c. (HasField' f b c, Show c) => b -> Script c
debugField dataType = script do
    let var = getField @f dataType
    debug $ fieldName @f @b @c <> ": " <> show var
    return var

testFieldNames = script do
  let x = X "abc" 42
  debugField @"f" x
  debugField @"g" x
DA
David_Martins
Jan 2022

Thank you very much, I’ll review the need of using something like this.

← Back to Discussions