类型推断 F# - 如何生成新变量?
Type inference F# - how to generate fresh variables?
我正在尝试在 f# 中开发用于类型推断的算法 W,但我想了解如何正确编写用于生成新变量的函数。
其实我的功能是
let counter = ref -1
let generate_fresh_variable () : string =
let list_variables = ['a' .. 'z'] |> List.map string
counter.Value <- !counter + 1
list_variables.Item(!counter)
但我对这个解决方案不满意,有人可以给我其他更好的想法吗?
如果你真的想用一个不纯的函数来做这个,我会这样写:
let mutable counter = -1
let generate_fresh_variable () =
counter <- counter + 1
counter + int 'a'
|> char
|> string
备注:
- 参考单元格已过时。如果您需要杂质,请改用可变变量。 (或者,如果你真的想坚持使用参考单元格,更新它的规范方法是使用
:=
,而不是直接分配给底层 Value
。)
- 无需维护潜在变量名称列表(尤其是无需在每次生成新变量时重建整个列表)。
- 如果您需要超过 26 个变量会怎样?
如果您想使用一些更复杂的 F# 技巧,您可以使用序列表达式创建无限的名称序列(这使得处理循环和处理 >26 个名称变得非常容易):
let names = seq {
for i in Seq.initInfinite id do
for c in 'a' .. 'z' do
if i = 0 then yield string c
else yield string c + string i }
获取新名称的函数然后会从序列中选择下一个名称。您需要使用底层枚举器来执行此操作。另一个不错的技巧是将状态隐藏在局部变量和 return 使用 lambda 的函数中:
let freshName =
let en = names.GetEnumerator()
fun () ->
ignore(en.MoveNext())
en.Current
然后根据需要多次调用 freshName()
。
我正在尝试在 f# 中开发用于类型推断的算法 W,但我想了解如何正确编写用于生成新变量的函数。
其实我的功能是
let counter = ref -1
let generate_fresh_variable () : string =
let list_variables = ['a' .. 'z'] |> List.map string
counter.Value <- !counter + 1
list_variables.Item(!counter)
但我对这个解决方案不满意,有人可以给我其他更好的想法吗?
如果你真的想用一个不纯的函数来做这个,我会这样写:
let mutable counter = -1
let generate_fresh_variable () =
counter <- counter + 1
counter + int 'a'
|> char
|> string
备注:
- 参考单元格已过时。如果您需要杂质,请改用可变变量。 (或者,如果你真的想坚持使用参考单元格,更新它的规范方法是使用
:=
,而不是直接分配给底层Value
。) - 无需维护潜在变量名称列表(尤其是无需在每次生成新变量时重建整个列表)。
- 如果您需要超过 26 个变量会怎样?
如果您想使用一些更复杂的 F# 技巧,您可以使用序列表达式创建无限的名称序列(这使得处理循环和处理 >26 个名称变得非常容易):
let names = seq {
for i in Seq.initInfinite id do
for c in 'a' .. 'z' do
if i = 0 then yield string c
else yield string c + string i }
获取新名称的函数然后会从序列中选择下一个名称。您需要使用底层枚举器来执行此操作。另一个不错的技巧是将状态隐藏在局部变量和 return 使用 lambda 的函数中:
let freshName =
let en = names.GetEnumerator()
fun () ->
ignore(en.MoveNext())
en.Current
然后根据需要多次调用 freshName()
。