+
+package main
+
+import (
+ "fmt"
+ "encoding/json"
+ "reflect"
+)
+
+// Unmarshal json to a struct containing interface field. See full
+// corresponding Haskell code in separate file.
+
+// Haskell:
+// class I a where
+// f :: a -> ()
+type I interface {
+ f()
+}
+
+type S struct {
+ X int
+}
+
+var _ I = S{}
+func (s S) f() {}
+
+// Haskell: data R1 = forall a. I a => R1 a Int
+// I.e. data constructor type is 'R1 :: forall a. I a => a -> Int -> R1',
+// and the type is existential.
+type R1 struct {
+ I I
+ Y int
+}
+
+// Haskell: data R2 a = R2 a Int
+// I.e. data constructor type is 'R2 :: forall a. a -> Int -> R2 a',
+// and this is regular (not existential) type.
+type R2[T any] struct {
+ I T
+ Y int
+}
+
+// Version of 'S' with pointer receiver for use with 'R3'.
+type SP struct {
+ X int
+}
+
+var _ I = (*SP)(nil)
+func (s *SP) f() {}
+
+// Haskell does not have reflect, so there is no equivalent of 'R3'.
+type R3 struct {
+ I I
+ Y int
+}
+
+func (r *R3) UnmarshalJSON(bs []byte) (err error) {
+ v := struct {
+ I json.RawMessage
+ Y int
+ }{}
+
+ err = json.Unmarshal(bs, &v)
+ if err != nil {
+ return
+ }
+ r.Y = v.Y
+
+ if r.I != nil {
+ p := reflect.ValueOf(r.I)
+ if p.Kind() != reflect.Pointer {
+ err = fmt.Errorf("R3.UnmarshalJSON(): Interface 'r.I' uses value receiver '%v'", p.Type())
+ return
+ }
+
+ if err = json.Unmarshal(v.I, p.Interface()); err != nil {
+ return
+ }
+ }
+
+ return
+}
+
+// Haskell:
+// class Read a => I2 a where
+// f2 :: a -> ()
+type I2 interface {
+ f2()
+ json.Unmarshaler
+}
+
+type S2 struct {
+ X int
+}
+
+// Dummy instance, but it's required by 'I2'.
+var _ json.Unmarshaler = (*S2)(nil)
+func (s *S2) UnmarshalJSON(bs []byte) error {
+ v := struct {X int}{}
+ if err := json.Unmarshal(bs, &v); err != nil {
+ return err
+ }
+ s.X = v.X
+ return nil
+}
+
+// Implementing I2 with value receiver has no sense, because
+// 'json.Unmarshaler' can only work with pointer receiver.
+var _ I2 = (*S2)(nil)
+func (s *S2) f2() {}
+
+// Haskell: data R4 = forall a. I2 a => R4 a Int
+// I.e. data constructor is: 'R4 :: forall a. I2 a => a -> Int -> R4'
+type R4 struct {
+ I I2
+ Y int
+}
+
+// json.UnmarshalJSON() method in Go has a pointer to actual data, so it
+// actually does know what type is behind existential interface 'I2'. But
+// Haskell only uses types and does not look at values during type check.
+// Therefore, a function equivalent to 'json.UnmarshalJSON()' should have a
+// type witness, which tell Haskell, which type to use for interface 'I2'. So,
+// the implementation of 'json.Unmarshaler will look like:
+//
+// class Unmarshaler b a where
+// read' :: Proxy a -> String -> b
+//
+// and an instance for R4 will be:
+//
+// instance I2 a => Unmarshaler R4 a where
+
+func main() {
+ jsBytes := []byte(`{"I": {"X": 1}, "Y": 2}`)
+
+ var err error
+
+ r1 := R1{}
+ err = json.Unmarshal(jsBytes, &r1)
+ fmt.Printf("R1: err = %v, r1 = %v\n", err, r1)
+
+ r2 := R2[S]{}
+ err = json.Unmarshal(jsBytes, &r2)
+ fmt.Printf("R2: err = %v, r2 = %v\n", err, r2)
+
+ r3 := R3{I: S{}}
+ err = json.Unmarshal(jsBytes, &r3)
+ fmt.Printf("R3{S}: err = %v, r3 = %v\n", err, r3)
+
+ r3p := R3{I: &SP{}}
+ err = json.Unmarshal(jsBytes, &r3p)
+ fmt.Printf("R3{SP}: err = %v, r3p = %v, r3p.I = %v\n", err, r3p, r3p.I)
+
+ r4 := R4{I: &S2{}}
+ err = json.Unmarshal(jsBytes, &r4)
+ fmt.Printf("R4: err = %v, r4 = %v, r4.I = %v\n", err, r4, r4.I)
+}