作者:mobiledu2502884483 | 来源:互联网 | 2023-06-05 11:03
我在 Haskell 中遇到了一些非常不直观的行为,我不确定它是否是 Haskell 中的错误。如果这是预期行为,具体是什么导致无限循环?import Data.Function (fix)main=
我在 Haskell 中遇到了一些非常不直观的行为,我不确定它是否是 Haskell 中的错误。如果这是预期行为,具体是什么导致无限循环?
import Data.Function (fix)
main=putStrLn$show$fst$
fix (rec-> ((a1,a2)->(3,7)) rec)
无限循环,我假设是因为将 rec 模式匹配到 rec (a1,a2) 它评估。但我觉得它不应该需要,因为一切都会匹配。例如,这些都可以正常工作:
fix (rec-> (a->(3,7)) rec)
fix (rec-> (a->let (a1,a2)=a in (3,7)) rec)
有趣的是这退出错误
fix (rec-> ((a1,a2)->(3,7)) undefined)
但是我可以发誓,我遇到这种行为(更复杂)的原始代码在这种情况下实际上会起作用。我可以尝试重新创建它。
回答
正确,元组模式匹配不是懒惰的。事实上,除了两个值得注意的例外,没有模式匹配是 lazy。粗略地讲,模式匹配的“要点”是强制对比赛的监督者进行评估。
当然,模式匹配可能出现在懒惰意味着永远不会执行的地方;例如,
const 3 (case loop of (_, _) -> "hi!")
不会循环。但这并不是因为匹配是惰性的——而是因为它const
是惰性的并且从不导致执行匹配。你的let
例子是类似的,因为语义let
是它绑定的变量在评估let
.
两个值得注意的例外之一是特殊的模式修饰符,~
; 放在~
模式之前表示使匹配变得惰性,因此向编译器声明修改后的模式始终匹配。(如果它不匹配,一旦强制绑定变量之一,您就会崩溃,而不是通常的下一个模式行为!)因此,对您的解决方法fix
是:
fix (rec -> ( ~(a1, a2) -> (3, 7)) rec)
当然,rec
不需要明确的名称。你也可以这样写:
fix ( ~(a1, a2) -> (3, 7))
另一个值得注意的例外是新类型匹配,这里不相关。
@DarrenSmith, no, tuples could not be defined with `newtype`. Only single constructor, *single field* types can. And whether they *should* be depends on context (usually yes, sometimes no).