# Specifying symbol type for \`HasField x r a\`

**URL:** <https://forum.canton.network/t/specifying-symbol-type-for-hasfield-x-r-a/701>\
**Category:** App Development\
**Tags:** 1\_2\_0, daml-sdk\
**Created:** [June 22, 2020, 9:00am UTC](https://forum.canton.network/t/specifying-symbol-type-for-hasfield-x-r-a/701 "2020-06-22T09:00:38Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Luciano](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/luciano/32/319_2.png) [@Luciano](https://forum.canton.network/u/Luciano)\
**Post date:** [June 22, 2020, 9:00am UTC](https://forum.canton.network/t/specifying-symbol-type-for-hasfield-x-r-a/701/1 "2020-06-22T09:00:38Z")

</div>

I know that the [HasField typeclass](https://docs.daml.com/daml/stdlib/DA-Record.html#class-da-internal-record-hasfield-39480) is used to access fields in DAML using the dot notation. e.g. `foo.a.b.c` as I’ve seen error message allude to this when I mistype a field name.

I’d like to use this to write a function wich _modifies_ data. Note you can’t do `foo.a.b.c = x`, and have to write instead `foo with a = foo.a.b with ...` which is really messy. I’d like to be able to write a function that takes the field name as parameter and then modifies it in some way.

For instance, say I have a data type:

```haskell
data Outer = Outer with 
  a: Option[Inner]
  b: List[Inner]

```

and I want to modify the `Inner` data type. I’ve come up with something like this:

```haskell
updateInner : (Functor f, HasField x Outer (f Inner)) => (Inner -> Inner) -> Outer -> Outer
updateInner fi o = setField (fmap fi (getField o)) o

```

To get this to compile I had to enable `AllowAmbiguousTypes` language feature. But even so, calls to this function complain about `x` being ambiguous at the call site. Note the type-class is declared as

```haskell
class HasField x r a where

    getField
        : r -> a

    setField
        : a -> r -> r

```

You see, `x` is only in the class declaration, but it’s not passed in as a parameter to either of the functions.

Is there a way to work around this?

I’ve tried to specify the type of `inner` to be `a` like so `updateInner @"a" (\inner -> ...) outer`, but it complains that `x` is of the wrong kind (`Symbol`).

I’ve tried adding `x` as a parameter to the function, but the compiler complains similarly. Some googling has shown that there is a `Proxy` type in Haskell that allows you to work around this, but I don’t think it’s in the DAML stdlib.

---

<div class="post-metadata">

**Author:** ![Martin\_Huschenbett](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/martin_huschenbett/32/372_2.png) [@Martin\_Huschenbett](https://forum.canton.network/u/Martin_Huschenbett)\
**Post date:** [June 22, 2020, 12:25pm UTC](https://forum.canton.network/t/specifying-symbol-type-for-hasfield-x-r-a/701/2 "2020-06-22T12:25:26Z")

</div>

Hi Luciano,

that’s a very interesting problem. The solution mostly involves sprinkling a few more types across your code. Despite that, you will still need to enable the `AllowAmbiguousTypes` language extension because the type parameter `f` only appears within the type class constraints.

First of all, you need to tell the compiler that you want to access the `x` field in `updateInner`'s `setField` and `getField`:

```haskell
updateInner : forall x f. (Functor f, HasField x Outer (f Inner)) => (Inner -> Inner) -> Outer -> Outer
updateInner fi o = setField @x (fmap fi (getField @x o)) o

```

Notice how we added `@x` type applications to `setField` and `getField`. For `x` to be in scope at these places, we need to _explicitly_ introduce it (and also `f`) using the `forall x f.` abstraction in the type signature of `updateInner`. Having the `x` as the first type parameter makes call sites more convenient since you only have to provide the field name, as in `updateInner @"a"`, and don’t need to provide the functor, for field `a` it would be `Optional` here. Thus, if we assume `type Inner = Int`, we can use `updateInner` like

```haskell
incrementA : Outer -> Outer
incrementA outer = updateInner @"a" (\i -> i + 1) outer

```

I hope that solves your problem,

Martin.

---

<div class="post-metadata">

**Author:** ![Luciano](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/luciano/32/319_2.png) [@Luciano](https://forum.canton.network/u/Luciano)\
**Post date:** [June 22, 2020, 12:38pm UTC](https://forum.canton.network/t/specifying-symbol-type-for-hasfield-x-r-a/701/3 "2020-06-22T12:38:26Z")

</div>

Hey @Martin_Huschenbett , thank you for that lengthy explanation. That was in fact really helpful - I’ve previously seen `forall` many times, but often as not I could just leave it out and my code would compile fine. But now I understand what it actually does! It’s made a lot of things clear for me beyond this particular problem.

So, in retrospect, those error messages now make sense. The compiler expected the first type parameter to be `f` (because it appeared first in the function signature, it expected it first), and hence was complaining that type `Symbol` (of `x`) didn’t match `* -> *` (of `f`).

Thanks!

---

<div class="post-metadata">

**Author:** ![chris.norris](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/chris.norris/32/688_2.png) [@chris.norris](https://forum.canton.network/u/chris.norris)\
**Post date:** [June 22, 2020, 3:05pm UTC](https://forum.canton.network/t/specifying-symbol-type-for-hasfield-x-r-a/701/4 "2020-06-22T15:05:34Z")

</div>

> [@Luciano](#):
>
> ```haskell
> data Outer = Outer with 
> a: Option[Inner]
> b: List[Inner]
> 
> ```

You might use lenses and prisms in such a case (they have been implemented in daml, although Im not implying this is supported or advocated and you would need to pull in all the machinery).  
I’ve added a ‘c’ field to illustrate how the lenses can be rejigged to “get” at the list inside a list of tuples. You would use “set”-ters to create another outer with some (possibly) changed structure.

```haskell
data Outer = Outer with
  a : Optional [Inner]
  b : [[Inner]] 
  c : [(Text, [Inner])]

   deriving Show

_a : Lens' Outer (Optional [Inner])
_a = fieldLens @ "a"

_b : Lens' Outer [[Inner]]
_b = fieldLens @ "b"

_c : Lens' Outer [(Text, [Inner])]
_c = fieldLens @ "c"

let outer = Outer with a=Some [1,2], b=[[1..10]], c=[("In a Tuple", [1..10])]

```

Again using `type Inner= Int` , in a scenario these would be used as:

```haskell
  -- a
  debug $ over traversed (+1) $ outer ^. _a . _Some
  -- [2,3]

  -- b
  debug $ over (traversed . traversed) (* 10) $ outer ^. _b
  -- [[10,20,30,40,50,60,70,80,90,100]]

  -- c
  debug $ over (traversed . _2 . traversed ) (+10) $ outer ^. _c
  -- [("In a Tuple",[11,12,13,14,15,16,17,18,19,20])]

```

---

<div class="post-metadata">

**Author:** ![Luciano](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/luciano/32/319_2.png) [@Luciano](https://forum.canton.network/u/Luciano)\
**Post date:** [June 22, 2020, 3:15pm UTC](https://forum.canton.network/t/specifying-symbol-type-for-hasfield-x-r-a/701/5 "2020-06-22T15:15:54Z")

</div>

> [@chris.norris](#):
>
> You might use lenses

😁 That’s in fact where I was going next … I was curious whether it would be possible to write a ‘generic’ lens using this typeclass. I guess `fieldLens` does just that.

I wonder if you can write directly something like `outer ^. (fieldLens @"a" @Outer) . (fieldLens @"b" @B) ` without having to declare the lenses on a separate line?

---

<div class="post-metadata">

**Author:** ![chris.norris](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/chris.norris/32/688_2.png) [@chris.norris](https://forum.canton.network/u/chris.norris)\
**Post date:** [June 22, 2020, 3:25pm UTC](https://forum.canton.network/t/specifying-symbol-type-for-hasfield-x-r-a/701/6 "2020-06-22T15:25:56Z")

</div>

Yes, @Luciano, this is possible:

```haskell
  -- a
  debug $ over traversed (+1) $ outer ^. (fieldLens @"a" @Outer) . _Some
  -- [2,3]

  -- b
  debug $ over (traversed . traversed) (* 10) $ outer ^. (fieldLens @"b" @Outer)
  -- [[10,20,30,40,50,60,70,80,90,100]]

  -- c
  debug $ over (traversed . _2 . traversed ) (+10) $ outer ^. (fieldLens @"c" @Outer)
  -- [("Text",[11,12,13,14,15,16,17,18,19,20])]

```

---

<div class="post-metadata">

**Author:** ![Martin\_Huschenbett](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/martin_huschenbett/32/372_2.png) [@Martin\_Huschenbett](https://forum.canton.network/u/Martin_Huschenbett)\
**Post date:** [June 22, 2020, 4:11pm UTC](https://forum.canton.network/t/specifying-symbol-type-for-hasfield-x-r-a/701/7 "2020-06-22T16:11:50Z")

</div>

If you care about performance, please be very careful with your use of lenses. For instance, if you write code like

```haskell
set (fieldLens @"field_1") v_1 . set (fieldLens @"field_2") v_2 . ... . set (fieldLens @"field_n") v_n $ foo

```

you will allocate `n` intermediate records. If you record has `m` fields, this seemingly innocent line has a runtime and memory complexity of `O(n*m)`. It is incredibly hard to write an optimizer for a strict language like DAML which simplifies this into the straightforward

```haskell
foo with field_1 = v1; field_2 = v_2; ...; field_n = v_n

```

(And it is by no means easy to do so in a lazy language either.)

Currently, the latter also has a complexity of `O(n*m)` but we’re already working on reducing this to it’s optimal complexity of `O(n+m)`.

---

<div class="post-metadata">

**Author:** ![Luciano](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/luciano/32/319_2.png) [@Luciano](https://forum.canton.network/u/Luciano)\
**Post date:** [June 22, 2020, 5:26pm UTC](https://forum.canton.network/t/specifying-symbol-type-for-hasfield-x-r-a/701/8 "2020-06-22T17:26:42Z")

</div>

> [@Martin\_Huschenbett](#):
>
> Currently, the latter also has a complexity of `O(n*m)`

🤔 Do you really mean the second example i.e. `with` syntax? Or do you mean the lens example?

---

<div class="post-metadata">

**Author:** ![Martin\_Huschenbett](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/martin_huschenbett/32/372_2.png) [@Martin\_Huschenbett](https://forum.canton.network/u/Martin_Huschenbett)\
**Post date:** [June 23, 2020, 1:57pm UTC](https://forum.canton.network/t/specifying-symbol-type-for-hasfield-x-r-a/701/9 "2020-06-23T13:57:32Z")

</div>

> [@Luciano](#):
>
> Do you really mean the second example i.e. `with` syntax? Or do you mean the lens example?

I really mean the second example wih the `with` syntax. But as I said that’s the _current_ state of affairs and we’re alrady working on fixing it.

---

<div class="post-metadata">

**Author:** ![Martin\_Huschenbett](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/martin_huschenbett/32/372_2.png) [@Martin\_Huschenbett](https://forum.canton.network/u/Martin_Huschenbett)\
**Post date:** [August 3, 2020, 10:08am UTC](https://forum.canton.network/t/specifying-symbol-type-for-hasfield-x-r-a/701/10 "2020-08-03T10:08:05Z")

</div>

> [@Martin\_Huschenbett](#):
>
> Currently, the latter also has a complexity of `O(n*m)` but we’re already working on reducing this to it’s optimal complexity of `O(n+m)` .

The promised fix has [landed in master](https://github.com/digital-asset/daml/pull/6937) and will be contained in the next snapshot release and later on in DAML SDK 1.5.0.
