Gleam, a statically typed language for the Erlang VM

How is this defined?

This is one of constructors for the Strategy type in my snippet, declared as:

pub enum Strategy {
  MyStrategyEnumsTimeStrategy(TimeStrategy)
  MyStrategyEnumsOtherStrategy(OtherStrategy)
}

Ok, yeah that compiles now. Why is that necessary? I’m not sure I understand…

I’m not a Gleam expert yet, but…

Gleam has a pretty simple type system and AFAIK enum constructor names must be unique in the context they are available. So you can’t have

enum Role {
  User(String)
  SuperUser(String)
}

and

enum SuperUserRole {
  SuperUser(String)
  GodUser(String)
}

at the same time because when you’d try to use one of these types in code, e.g. by creating a SuperUser("mgwidmann"), the Gleam compiler wouldn’t know which type is this thing. Is it a Role or a SuperUserRole?

1 Like

I see what you are saying, but I’d argue there is a possible way to make that determination. Either the SuperUser is dead code in which case you cannot figure it out (and it probably doesn’t matter, this would be ok to error on) OR it is used somewhere with some other function or struct/object/whatever that gives you the information needed to know its type. The second, and most common, case would give that answer.

In my case, in the Strategy enum, I was attempting to refer to that type not create a new one, hence the confusion.

So it seems a union/sum/disjunctive type is not actually possible in the same way I expected…

That’s right! It is definitely a bug that Gleam allows you to define multiple constructors with the same name. If you have the time please open an issue for that. If not I’ll do it when I’m at a computer.

This is a really good observation and one I had not considered. Now that enums can have labelled fields they are effective equivalent to structs. I wonder if we really need both. What might a unified syntax look like?

type Person {
  Person(name: String)
}

type Size {
  Big
  Small
}

It would be nice to not have repeat the constructor name when there is only a single constructor. Perhaps it’s not a big deal

2 Likes

If type parameters had a separate designator, e.g. [] this could be

type Person(name: String)

equivalent to

type Person {
  Person(name: String)
}

but you could also write this as

type Person(
  name: String
)

and a parametrized type would look like

type Result[value, reason] {
  Ok(value)
  Error(reason)
}

(TBH I don’t care which paren type is used where)

edit: But I also don’t think it’s a big problem to write the type name twice

1 Like

What are your thoughts on how gleam should handle bit syntax in regards to types, construction, pattern matching? I couldn’t see anything on the gleam.run site.

1 Like

I would like to adopt the same system as Erlang but no work has yet been done here.

I’ve created an issue to discuss the change in custom type definition syntax here: https://github.com/gleam-lang/gleam/issues/355

As we’re discussing fairly large changes to the language I have also opened an issue to discuss whether we should make type annotations of top level functions mandatory: https://github.com/gleam-lang/gleam/issues/360

It’d be great to get the thoughts of other people on this. :slight_smile:

1 Like

I may be too late to the party but I like this a lot. :slight_smile: Using tuples will be more performant and the main reason Elixir used maps is because our polymorphism needs to happen at runtime but in Gleam it can be done exclusively at compile time. Type-erasure can be an issue, so annotating the first element will be very helpful!

Have you also considered naming them “records” after all? I don’t know how big of a role interoperability with Erlang/Elixir plays within Gleam but the inconsistent naming may cause a lot of confusion. Especially if you plan generate .hrl files.

Oh, another note! You may want to consider putting the generated .hrl files inside “include/” since any other directory may not be copied by build tools.

4 Likes

I think it makes sense to use the word “record” though I’ve not yet worked out exactly how it should all fit together.

Here’s my current thoughts:

pub type SchoolPerson {
  Student(name: String)
  Teacher(name: String, class: Subject)
  Guest
}

let louis = Student(name: "Louis")

SchoolPerson is a custom type.
Student, Teacher, and Guest are constructors of SchoolPerson
louis is a Student record of type SchoolPerson

Thanks for the tip, I’ve been putting them in src.

1 Like

This sounds good to me (but I don’t think sounding good to me means much). :slight_smile:

AFAIK, Erlang/OTP puts in src the .hrl files that are not meant to be shared. So if you have both public and private records, maybe you can follow their convention.

2 Likes

I think the convention is something like this:

  • Module level records - Defined in the module itself. Only used directly within the module
  • Application level records - Defined in an hrl file in src. Can be used by all modules in the project using the -include directive. (i.e -include('myhrl.hrl'))
  • Public records - Defined in hrl files in include directory. -include_lib('myapp/include/myapp.hrl')
2 Likes

Merry Christmas everyone! :christmas_tree:

https://lpil.uk/blog/gleam-v0.6-released/

16 Likes

Hi all!

I wrote a small decoding library for Gleam to aid in translating data from Elixir/Erlang/other BEAM languages into Gleam data. For those who are familiar, it’s basically a port of the patterns found in Elm’s JSON decoding library. My hope is that this will make it much easier for people to try out Gleam in one of their existing Elixir or Erlang projects, and to build bindings to other Erlang libraries.

You can find it here: https://github.com/rjdellecese/gleam_decode.

If you have any thoughts/ideas/suggestions for the library, or any questions about how to use it, please open an issue on GitHub!

5 Likes

This is brilliant! Thank you! I can see this being really useful :slight_smile:

Would you like to add a link to this list? To make it easier to discover? https://github.com/gleam-lang/awesome-gleam

2 Likes

Yesterday and today I took a little break from working on the language and instead had a crack at making some OTP compatible libraries, while enjoying some Christmas leftovers. :santa:

This library allows the programmer to create agent processes, which are a simple building block for creating stateful OTP compatible processes that can respond to both synchronous and asynchronous messages.

I could imagine agent (or something like it) being a common building block for OTP applications in Gleam, as gen_server is for Erlang, and GenServer is for Elixir.

3 Likes