Я пытаюсь смоделировать тип как объединение, в котором каждый член этого объединения имеет общие свойства со всеми другими членами.
Я сейчас достигаю этого примерно так:
type alias File = {
name : String
}
type CommonFileState extra = CommonFileState {
id : String
, file : File
} extra
type alias ValidFileState = CommonFileState {
validatedAt : Int
}
type alias InvalidFileState = CommonFileState {
reason : String
}
type alias LoadingFileState = CommonFileState {}
type FileState = Valid ValidFileState | Invalid InvalidFileState | Loading LoadingFileState
Теперь, если я хочу прочитать одно из этих общих свойств для любого заданного FileState
, я должен сопоставить каждого члена объединения:
getId : FileState -> String
getId fileState = case fileState of
Valid (CommonFileState {id} extra) -> id
Invalid (CommonFileState {id} extra) -> id
Loading (CommonFileState {id} extra) -> id
Мне кажется, что это неправильно, потому что я должен дублировать доступ к собственности для каждого участника. Если бы мне нужно было как-то манипулировать этим свойством (например, конкатенировать что-то в строку), мне также пришлось бы продублировать это.
Я хочу иметь возможность легко получать доступ к общим свойствам моего объединения и работать с этими общими свойствами.
Когда я начал искать другие способы сделать это, я обнаружил, что одной из альтернатив было вложить объединение в запись, которая также содержит общие свойства:
type alias ValidCurrentFileState = {
validatedAt : Int
}
type alias InvalidCurrentFileState = {
reason : String
}
type alias LoadingCurrentFileState = {}
type CurrentFileState = Valid ValidCurrentFileState | Invalid InvalidCurrentFileState| Loading LoadingCurrentFileState
type alias File = {
name : String
}
type alias FileState = {
id : String
, file : File
, currentState : CurrentFileState
}
getId : FileState -> String
getId {id} = id
Однако это неудобно, потому что я должен назвать вложенное объединение, которое добавляет уровень ненужной косвенности: «состояние файла» и « текущее состояние файла» концептуально совпадают.
Есть ли другие способы сделать это, у которых нет проблем, о которых я говорил?