I am looking for a way when I have some untrusted source of data that structurally can be parsed.
But there might be validation rules, so record could be either valid or not.
Invalid data still can be processed: serialized, transferred or maybe even fixed to make it valid.
I came up with following solution. Is it acceptable?
Any drawbacks?
pub opaque type Validated(a, b) {
Valid(a)
Invalid(a, b)
}
pub type SchoolPerson {
Teacher(name: String, subject: String)
Student(name: String)
}
pub fn new_teacher(name, subject) {
Teacher(name, subject)
}
pub fn new_student(name) {
Student(name)
}
pub fn validate_person(person: SchoolPerson) -> Validated(SchoolPerson, String) {
case person {
Teacher(name, subject) -> {
case name {
"Mr" <> _ | "Ms" <> _ -> Valid(Teacher(name, subject))
_ ->
Invalid(
Teacher(name, subject),
"Teacher name must start with 'Mr' or 'Ms'",
)
}
}
Student(name) -> Valid(Student(name))
}
}
pub fn main() {
variant_a.new_teacher("Mr Schofield", "Physics")
|> io.debug
|> variant_a.validate_person
|> io.debug
variant_a.new_teacher("Dr Smith", "Maths")
|> io.debug
|> variant_a.validate_person
|> io.debug
variant_a.new_student("John")
|> io.debug
|> variant_a.validate_person
|> io.debug
}
Teacher("Mr Schofield", "Physics")
Valid(Teacher("Mr Schofield", "Physics"))
Teacher("Dr Smith", "Maths")
Invalid(Teacher("Dr Smith", "Maths"), "Teacher name must start with 'Mr' or 'Ms'")
Student("John")
Valid(Student("John"))