榆木:访问工会中的共同领域

时间:2019-07-05 19:16:26

标签: elm gadt union-types

我正在尝试将类型建模为联合,其中该联合的每个成员都具有与所有其他成员相同的属性。

我目前正在这样实现:

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

但是这很尴尬,因为我必须命名嵌套的并集,这增加了不必要的间接访问级别:“文件状态”和“ 当前文件状态”在概念上是相同的。

还有没有其他方法可以解决我提到的问题吗?

1 个答案:

答案 0 :(得分:1)

我认为您正在思考这种错误的方法。

(在Elm中)建模的目的是捕获数据的可能状态,并在模型中排除“不可能”状态,以便编译器可以静态地防止代码每次创建此类状态。

一旦对模型感到满意,就可以编写所需的帮助程序,以使核心逻辑易于表达和维护。

我怀疑我通常会采用第二种方法,但是我不知道您需要解决的所有问题。