Fl4m3Ph03n1x

Fl4m3Ph03n1x

How to convert a typed definition to a typedstruct?

Background

I am moving towards defined data structures in my application, and I find that TypedStruct is quite useful.

Questions

However, I have recently found a little hickup. I don’t know how to convert this definition into a typedstruct:

  @type order_info :: %{
    (visible :: String.t()) => boolean,
    (order_type :: String.t()) => String.t(),
    (platform :: String.t()) => String.t(),
    (platinum :: String.t()) => non_neg_integer,
    (user :: String.t()) => %{
      (ingame_name :: String.t()) => String.t(),
      (status :: String.t()) => String.t()
    }
  }

My main issue here is the user map. Aside from the fact I don’t know how to define a typedstruct inside a trypedstruct, how do you folks do this?

  1. Do you simply define a map inside the order_info typedstruct and ignore the mandatory parameters for the user map?
  2. Do you create another typedstruct (called user) that goes inside the typedsctruct called order_info?
  3. What is the standard option in Elixir ?

Marked As Solved

Fl4m3Ph03n1x

Fl4m3Ph03n1x

Answer

After talking with other folks at the community I have opted for separating the User into a struct, in its own module, inside an OrderInfo directory:

lib/
  order_info/
    user.ex
  order_info.ex

I personally find this works great for readability. So for readability purposes this is what I ended up with:

defmodule AuctionHouse.Data.OrderInfo.User do
  @moduledoc """
  Represents the account information for a User.
  """

  use TypedStruct

  alias AuctionHouse.Shared.Utils

  @type user :: %{
          (ingame_name :: String.t()) => String.t(),
          (status :: String.t()) => String.t()
        }

  typedstruct enforce: true do
    @typedoc "Account information of an User"

    field(:ingame_name, String.t())
    field(:status, String.t())
  end

  @spec new(user) :: __MODULE__.t()
  def new(
        %{
          "ingame_name" => ingame_name,
          "status" => status
        } = user
      )
      when is_binary(ingame_name) and is_binary(status),
      do: Utils.string_map_to_struct(user, __MODULE__)
end

An then OrderInfo is basically the same, as seen by this typedstruct definition:

  typedstruct enforce: true do
    @typedoc "Information about an order"

    field(:visible, boolean())
    field(:order_type, String.t())
    field(:platform, String.t())
    field(:platinum, non_neg_integer())
    field(:user, __MODULE__.User.t())
  end

Extra

One thing to mention here, is that struct will not convert string maps to structures, only atom maps. So in order to achieve my goal of converting string maps to structures, I created this little helper function:

defmodule AuctionHouse.Shared.Utils do
  @moduledoc """
  Set of functions used across the app, for utility purposes, like dealing with
  tuples, maps and other data structures.
  """

  alias Morphix

  @spec string_map_to_struct(data :: map, target_struct :: module | struct) ::
          target_struct :: struct
  def string_map_to_struct(data, target_struct) do
    data
    |> Morphix.atomorphiform!()
    |> data_to_struct(target_struct)
  end

  @spec data_to_struct(data :: Enumerable.t(), target_struct :: module | struct) ::
          target_struct :: struct
  def data_to_struct(data, target_struct), do: struct(target_struct, data)
end

Here I used Morphix to do the hard work, but this can also be achieved by other means, see:

Many thanks to all of the people who helped me get this far, from other communities as well:

Where Next?

Popular Backend topics Top

Jsdr3398
I’m trying to create a router where everything is in a collection of routes (similar to how I do my routes in expressjs). But it doesn’t ...
New
jaimeiniesta
I maintain a project that lists hundreds of thousands of web pages, and I’d like to show a screenshot for each web page. There are alread...
New
mrmurphy
I’ve run into a situation where I’ve got a list of posts inside of a container that uses phx-update=“prepend”, and the posts on the socke...
New
Ookma-Kyi
I am learning Elixir at the moment but am finding it difficult to learn. The issue is there aren’t any good tutorial sites out there when...
New
Fl4m3Ph03n1x
Background I am trying out polymorphic typing with dialyzer. As an example I am using the famous Option type (aka, Maybe Monad) that is n...
New
JimmyCarterSon
Hello, I am working on a new application with Elixir, Dish_out. I want to see Data I follow this tutorial with Elixir Casts. However, I ...
New
Fl4m3Ph03n1x
Background I am a fan of dialyzer and friends (looking at Gradient) and I try to have sepcs in my code as much as I can. To this end, I a...
New
Fl4m3Ph03n1x
Background I have a phoenix application in Windows 11. Unfortunately for me, I cannot compile the application because of a dependency err...
New
harwind
I’m presently working on a backend development project to build a RESTful API using Python and Flask. The Scaler backend developer site h...
New
harwind
I have a large SQL database with millions of records, and I’ve identified duplicate entries. What’s the most efficient way to find and re...
New

Other popular topics Top

PragmaticBookshelf
Free and open source software is the default choice for the technologies that run our world, and it’s built and maintained by people like...
New
PragmaticBookshelf
Write Elixir tests that you can be proud of. Dive into Elixir’s test philosophy and gain mastery over the terminology and concepts that u...
New
PragmaticBookshelf
Rust is an exciting new programming language combining the power of C with memory safety, fearless concurrency, and productivity boosters...
New
Exadra37
Oh just spent so much time on this to discover now that RancherOS is in end of life but Rancher is refusing to mark the Github repo as su...
New
PragmaticBookshelf
Build highly interactive applications without ever leaving Elixir, the way the experts do. Let LiveView take care of performance, scalabi...
New
New
AstonJ
Was just curious to see if any were around, found this one: I got 51/100: Not sure if it was meant to buy I am sure at times the b...
New
New
AstonJ
This is cool! DEEPSEEK-V3 ON M4 MAC: BLAZING FAST INFERENCE ON APPLE SILICON We just witnessed something incredible: the largest open-s...
New
AstonJ
Curious what kind of results others are getting, I think actually prefer the 7B model to the 32B model, not only is it faster but the qua...
New