I have a typeclass that looks like this:

```
module Observation where
import Prelude
import Prelude qualified as P ((+))
class Observation f a where
konst : a -> f a
(+) : f a -> f a -> f a
(===): f a -> f a -> f Bool
```

This generates an expression tree, which I would like to be able to serialize to the ledger. I can use it to write expression such as:

```
(kons 1 + kons 2) === konst 3
```

To achieve this, I’ve taken the approach similar to that described in Functions - Can we pass them as arguments in a choice? , of encoding it as a data type `Obs`

:

```
instance Observation Obs a where
konst = Const
(+) = Add
(===) = Equals -- FAILS TO COMPILE
data Obs a
= Const a
| Add with lhs: Obs a, rhs: Obs a
| Equals with lhs: Obs a, rhs: Obs a
```

Now this doesn’t work - error on the implementation of `(===) = Equals`

. The reason is that in the typeclass, this requires a return type of `Obs Bool`

, but the ADT constructor `Equals`

infers an `Obs a`

.

This is practically the motivating problem described for `GADTs`

in the Haskell wiki. This language feature doesn’t quite work in DAML unfortunately.

@cocreature Also suggested I look at using a different encoding using the Yoneda lemma. An example is given in this blog post, about half way down the page. But you’ll notice the transformation embeds a function into the ADT, which is not serializable, so that doesn’t help.

I also considered splitting up the algebra in two, with boolean algebra looking something like this:

```
data Boolean
= Equals : forall a . (Obs a, Obs a)
...
```

You’ll notice this data type doesn’t have a type parameter `a`

so it’s not inferred. But this also requires a language feature that isn’t supported.

Finally, I should mention that there are a couple of not-so-great solutions, such as ‘tagging’ the type `a`

, by using e.g. `Either a Bool`

instead. This has the major disadvantage that writing expressions will no longer warn of type errors at compile-time. For example, the expression

```
Left 1 === Right false
```

would compile fine (although it would throw an error at runtime).

I’m fresh out of ideas. Could anybody suggest an alternative approach?