Struct Embedding in PureScript

PureScript supports record types, which are similar to structs in other languages. We can use them to express a composition of types. Here’s an example demonstrating this concept:

module Main where

import Prelude
import Effect (Effect)
import Effect.Console (log)

type Base = 
  { num :: Int }

describe :: Base -> String
describe b = "base with num=" <> show b.num

-- A `Container` includes a `Base`. In PureScript, this is done
-- through composition rather than embedding.
type Container = 
  { base :: Base
  , str :: String
  }

main :: Effect Unit
main = do
  -- When creating records, we initialize all fields explicitly
  let co = { base: { num: 1 }, str: "some name" }

  -- We can access the base's fields through the `base` field of `co`
  log $ "co={num: " <> show co.base.num <> ", str: " <> co.str <> "}"

  -- We can also access the full path using the field names
  log $ "also num: " <> show co.base.num

  -- We can call the `describe` function with the `base` field of `co`
  log $ "describe: " <> describe co.base

  -- In PureScript, we use typeclasses for interface-like behavior
  class Describer a where
    describer :: a -> String

  -- We can make `Container` an instance of `Describer`
  instance describerContainer :: Describer Container where
    describer c = describe c.base

  -- Now we can use the `describer` function with our `Container`
  log $ "describer: " <> describer co

To run this program, you would typically use the PureScript compiler (purs) and Node.js:

$ purs compile src/**/*.purs
$ node -e "require('./output/Main').main()"
co={num: 1, str: some name}
also num: 1
describe: base with num=1
describer: base with num=1

In this PureScript version, we’ve translated the concept of struct embedding to record composition. PureScript uses record types and functions to achieve similar behavior to Go’s struct methods. The Describer typeclass is used to mimic the interface behavior from the Go example.