Skip to content
This repository was archived by the owner on Jun 17, 2022. It is now read-only.
This repository was archived by the owner on Jun 17, 2022. It is now read-only.

attached type parameters #121

@aep

Description

@aep

generic containers work, but i still hate them somehow. i thought not knowing the interior type is fine because thats what golang does too, but then golang has reflection so you can get the interior at runtime.

this is unfixably unsafe

new+10  v = map::make();

u8 val =12;
v.insert("hello", &val);

u64 * bad = v.get("hello"); 

well , not unfixable, vec could just store the typeid, but then it's checked at runtime, which is terrible.

new+10  v = map::make();

u8 val =12;
v.insert("hello", &val);

u64 meh;
v.get("hello", &meh);

typestate would help

struct Vec+t {   
}

theory item (Vec self) typeid;

pub fn get(Vec+t mut * self)  void  *
  model  typeid(return) == item(self)
{
}

pub fn main() {

  new+10  v = vec::make();
   static_attest(val::item(&v) ==  typeid(u8));

   u8 val =12;
   v.push(&val);

   u64 * bad = v.get("hello"); // error: implicit cast of  void pointer to different type 
}

this elegantly fits into the powerful smt theories, but it doesn't answer the question of how to decode a struct from json

struct Foo {   
  Vec::vec+100 something;  // dunno which type is in this
}

Other languages do "templates" so they just create a new type for each possible parameter. That's horribly inefficient, as each instance also has to have all of its functions duplicated. It also doesnt map to C.

Instead i'm proposing to just attach the interiour typestate to the external typestate permanently somehow, creating a new virtual type. That's essentially just what tail already is, a permanent type state.

One possible syntax is just reusing the familiar template angled brackets. however, the tail marker has to go somewhere

struct Vec<typeid Item>
struct Vec+t<typeid Item>
struct Vec<typeid Item>+t
struct Vec<typeid Item, +t>


pub fn get (Vec<Item, +t> mut * self)  void<Item> *
{
}

pub fn main() {
    new<u8,+10>  v = vec::make();

    u8 val =12;
    v.push(&val);

    u64 * bad = v.get("hello");  // error: implicit cast of  void<u8> pointer to wrong type 
}

benefit is, it looks immediately familiar. disadvantage is that the familiarity is a trap. This is not a template, and you cannot actually use it in place of a typename.

struct VecWrapper<typeid Item> {
    Vec<Item> inner; // ok
    Item example;      // nope, Item is a typeid, not a type
}

i personally also think angled brackets are a terrible syntactical choice because they're also math operators, but that's what the world agreed on, so be it. We could of course use square brackets or whatever.

struct Vec[typeid Item, +t]

another way to deal with this is creating a way to make integrity theories permanent somehow.

  struct Vec+t {}

  theory item (Vec self) typeid;

  type ByteVec = Vec+t
     where item(self) = typeid(u8)
  ;


  struct A+
  {
    ByteVec+ buffer;
  }

it's difficult to decide between these two options. Allowing a type alias that includes a permanent smt theory is very powerful, but also difficult to understand. The type "templates" are immediately obvious.

Metadata

Metadata

Assignees

Labels

need-realworld-feedbackfeedback from users needed on how the decision would affect real world use

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions