F#二叉搜索树

F#二叉搜索树,f#,binary-search-tree,F#,Binary Search Tree,我正在尝试在F#中实现BST。因为我是从F#开始我的旅程的,所以我想寻求帮助 我有一个简单的测试 [<Fact>] let ``Data is retained`` () = let treeData = create [4] treeData |> data |> should equal 4 treeData |> left |> should equal None treeData |> right |> sh

我正在尝试在F#中实现BST。因为我是从F#开始我的旅程的,所以我想寻求帮助

我有一个简单的测试

[<Fact>]
let ``Data is retained`` () =
    let treeData = create [4]
    treeData |> data |> should equal 4
    treeData |> left |> should equal None
    treeData |> right |> should equal None
以及由此产生的错误:

FS0001类型不匹配。期待 ''a->Tree->Tree将其类型签名显示为:

List.fold : ('State -> 'T -> 'State) -> 'State -> 'T list -> 'State
让我们把它打开。第一个参数是类型为
'State->'T->'State
的函数。这意味着它接受一个状态和一个类型为T的参数,并返回一个新状态。在这里,状态是您的
类型:从一个基本的
叶开始
,一步一步地构建树。
List.fold的第二个参数是初始状态(在本例中为
Leaf
),第三个参数是要折叠的T型项目列表

您的第二个和第三个参数是正确的,但您的第一个参数与
List.fold所需的签名不一致<代码>列表。fold
需要类型为
'State->'T->'State
的东西,在您的情况下是
树插入5
。因此,我强烈建议您不要更改
insert
函数的参数顺序

因此,如果您不应该更改
insert
函数的参数顺序,但是它们与
List.fold
一起使用的顺序错误,您会怎么做?简单:创建一个参数翻转的匿名函数,这样就可以将
insert
List一起使用。fold

let create items = 
    List.fold (fun tree item -> insert item tree) Leaf items
现在我们将更进一步,对其进行推广。实际上,在F#编程中,发现双参数函数的参数在大多数情况下都是正确的,但在一个特定的用例中却是错误的。为了解决这个问题,有时创建一个名为
flip
的通用函数很有用:

let flip f = fun a b -> f b a
然后您可以像这样编写
create
函数:

let create items = 
    List.fold (flip insert) Leaf items
let flip f a b = f b a
有时使用
flip
会使代码更加混乱,而不是减少混乱,因此我不建议一直使用它。(这也是为什么F#standard library中没有
flip
函数的原因:因为它并不总是最好的解决方案。而且因为自己编写它很简单,所以在标准库中缺少它也没什么大不了的)。但有时使用
flip
会使代码更简单,我认为这就是其中之一

另外,
flip
函数也可以这样编写:

let create items = 
    List.fold (flip insert) Leaf items
let flip f a b = f b a
此定义与我在主要示例中使用的
let flip f=fun a b->f b a
定义相同。您知道原因吗?

显示其类型签名为:

List.fold : ('State -> 'T -> 'State) -> 'State -> 'T list -> 'State
让我们把它打开。第一个参数是类型为
'State->'T->'State
的函数。这意味着它接受一个状态和一个类型为T的参数,并返回一个新状态。在这里,状态是您的
类型:从一个基本的
叶开始
,一步一步地构建树。
List.fold的第二个参数是初始状态(在本例中为
Leaf
),第三个参数是要折叠的T型项目列表

您的第二个和第三个参数是正确的,但您的第一个参数与
List.fold所需的签名不一致<代码>列表。fold
需要类型为
'State->'T->'State
的东西,在您的情况下是
树插入5
。因此,我强烈建议您不要更改
insert
函数的参数顺序

因此,如果您不应该更改
insert
函数的参数顺序,但是它们与
List.fold
一起使用的顺序错误,您会怎么做?简单:创建一个参数翻转的匿名函数,这样就可以将
insert
List一起使用。fold

let create items = 
    List.fold (fun tree item -> insert item tree) Leaf items
现在我们将更进一步,对其进行推广。实际上,在F#编程中,发现双参数函数的参数在大多数情况下都是正确的,但在一个特定的用例中却是错误的。为了解决这个问题,有时创建一个名为
flip
的通用函数很有用:

let flip f = fun a b -> f b a
然后您可以像这样编写
create
函数:

let create items = 
    List.fold (flip insert) Leaf items
let flip f a b = f b a
有时使用
flip
会使代码更加混乱,而不是减少混乱,因此我不建议一直使用它。(这也是为什么F#standard library中没有
flip
函数的原因:因为它并不总是最好的解决方案。而且因为自己编写它很简单,所以在标准库中缺少它也没什么大不了的)。但有时使用
flip
会使代码更简单,我认为这就是其中之一

另外,
flip
函数也可以这样编写:

let create items = 
    List.fold (flip insert) Leaf items
let flip f a b = f b a

此定义与我在主要示例中使用的
let flip f=fun a b->f b a
定义相同。你知道为什么吗?

尝试在
insert
函数中切换参数顺序
let rec insert targetTree newValue
@Szer-我不建议在
insert
中切换参数顺序:它实际上已经是用于
|>
运算符的正确顺序,如我的回答所示。尝试在
insert
函数中切换参数顺序
let rec insert targetTree newValue
@Szer-我不建议在
insert
中切换参数顺序:它实际上已经用于
|>
操作符,如我的回答所示。非常感谢您帮助理解所有这些!关于你的问题,;我认为第一个flip函数只是使用翻转的参数调用传递的函数。在第二种情况下,我们将替换函数。这让我想起了javascript代码测试,在那里你可以轻松地替换函数,而不是编写模拟。在这两种情况下,当你