我想更新一个字段中的更改记录语法,所以我做了类似的事情:
let rec = rec{field = 1}
Run Code Online (Sandbox Code Playgroud)
但我注意到我不能再打印rec了,这意味着当我尝试时编译器似乎进入无限循环.所以我尝试过:
let a = 1 -- prints OK
let a = a -- now i can't print a (also stuck in a loop)
Run Code Online (Sandbox Code Playgroud)
所以我不能let a = a用任何类型,但我不明白为什么,我应该如何解决这个问题.
顺便说一句:在做的时候:
let b = a {...record changes..}
let a = b
Run Code Online (Sandbox Code Playgroud)
有效,但似乎多余.
您正在运行到的问题是,所有 let和where绑定在Haskell在默认情况下递归.所以当你写作
let rec = rec { ... }
Run Code Online (Sandbox Code Playgroud)
它试图定义一个循环数据类型,当你尝试评估它时会永远循环(就像let a = a).
这没有真正的方法 - 这是语言的权衡.它使得递归函数(甚至是普通值)更容易编写,噪音更少,但也意味着你不能轻易地重新定义a一堆本身.
你真的可以做的唯一的事情就是给你的价值观不同业者名称,rec并rec'会做到这一点的常用方法.
为了公平对待Haskell,递归函数甚至递归值经常出现.代码就像
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
Run Code Online (Sandbox Code Playgroud)
一旦你掌握了它就可以非常好,而不必明确地将这个定义标记为递归(就像你必须要做的那样,比如OCaml)是一个明确的好处.