如何基于递归类型别名初始化值?
type alias ContentProvider =
{ profile : Profile
, topics : List Topic
, links : Links
, subscribers : Subscribers
}
type Subscribers
= Subscribers (List ContentProvider)
我尝试初始化值失败:
contentProvider1 : ContentProvider
contentProvider1 =
ContentProvider profile1 topics contentProvider1Links (Subscribers [ contentProvider2, contentProvider3 ])
请注意,最后一个参数导致错误:
(Subscribers [ contentProvider2, contentProvider3 ])
contentProvider1
以偷偷摸摸的方式定义, 导致无限循环。 - 以下定义直接取决于 在彼此:┌─────┐ │ contentProvider1 │ ↓ │ contentProvider2 │ ↓ │ contentProvider3 └─────┘
我引用了此documentation。但是,我不明白为什么我仍然遇到编译器错误。
附录
contentProvider1 : ContentProvider
contentProvider1 =
ContentProvider profile1 topics contentProvider1Links (Subscribers [ contentProvider2 ])
contentProvider2 : ContentProvider
contentProvider2 =
ContentProvider profile2 topics contentProvider2Links (Subscribers [ contentProvider1, contentProvider3 ])
contentProvider3 : ContentProvider
contentProvider3 =
ContentProvider profile3 topics contentProvider3Links (Subscribers [ contentProvider1, contentProvider2 ])
答案 0 :(得分:3)
你的代码在语法上是正确的,在Elm 0.18之前,它会被编译。但是当你运行程序时,你最终会陷入堆栈溢出,无限循环(因为尾部调用递归优化)或运行时异常because of a compiler bug that has since been fixed。
考虑运行时扩展contentProvider1
所需的内容:
contentProvider1
,其中引用了contentProvider2
contentProvider2
,其中引用了contentProvider1
contentProvider1
,其中引用了contentProvider2
您所遇到的是Elm的超级有用的编译器,可以保存您无法使用的代码。仍然可以编写一个非暂停函数(and always will be),但是Elm的编译器现在会检查一些在运行时会爆炸的常见情况。
Here is some documentation that more thoroughly explains the reasoning behind this compiler error
答案 1 :(得分:1)
contentProvider2和contentProvider3需要像Chad Gilbert那样定义,但这里的问题不是你的相互递归类型别名,而是circular value reference that is not possible。以下是编译的简化示例:
type alias ContentProvider =
{ profile : String
, topics : List String
, links : String
, subscribers : Subscribers
}
type Subscribers =
Subscribers (List ContentProvider)
contentProvider1 : ContentProvider
contentProvider1 =
ContentProvider "profile" ["art", "science"] "test" (Subscribers [contentProvider2])
contentProvider2 : ContentProvider
contentProvider2 =
ContentProvider "profile" ["art", "science"] "test" (Subscribers [])