#Phantom Types and the limits of record spreading

1 messages · Page 1 of 1 (latest)

steady zodiac
#

For my UI component library, I'm adding support for props, using the builder pattern (so the user doesn't have to specify all the fields).
And I'm trying to use the phantom types, because they seem cool, but with a slight modification.
Here's an example:

pub type NoOnInput =
  Nil

pub type OnInput(msg) =
  fn(TextState) -> msg

pub type NoValue =
  Nil

pub type Value = String

pub type TextProps(on_input, value) {
  TextProps(
    on_input: on_input,
    type_: String,
    placeholder: option.Option(String),
    value: value,
  )
}

pub fn init() -> TextProps(NoOnInput,NoValue) {
  TextProps(on_input: Nil, type_: "text", placeholder: option.None, value: Nil)
}

pub fn with_value(props: TextProps(i, NoValue), value: Value) -> TextProps(i, Value) {
  TextProps(
    on_input: props.on_input,
    type_: props.type_,
    placeholder: props.placeholder,
    value: value,
  )
}

pub fn build(props: TextProps(OnInput,Value) {
    // here the type checker knows that oninput and value are not Nil
}

As you can see, the types are not that phantom, because I actually use them in the record. I think it's better that way, because then I don't have to do any asserts or anything.
But I've seen people not do that. So here's the first question: is there a reason to use actual phantom types, instead of whatever-it-is-im-doing?

Second thing: I see that we can't use record spreading if the input record is of a different type. Which makes sense for most cases, but I feel like in this case it's not an useful limitation (and even more so when using actual phantom types).
Is there a reason for this behaviour? Or is it just a limitation of the current type checker and I can expect it to be fixed SomeDay™?

thorn kernel
#

tada!