F#缩短树上的模式匹配

时间:2017-10-05 10:17:53

标签: f#

不确定这是否是这个问题的正确位置,但我有一个功能,我很确定可以简化,但我不确定如何。

let rec probOK = function
| Branch(ds, p, Leaf l1, Leaf l2) when p <= 1.0 && p >= 0.0     ->  true
| Branch(ds, p, b1, b2)           when p <= 1.0 && p >= 0.0     ->  probOK b1 && probOK b2
| Branch(ds, p , b1, Leaf l1)     when p <= 1.0 && p >= 0.0     ->  probOK b1
| Branch(ds, p , Leaf l2, b2)     when p <= 1.0 && p >= 0.0     ->  probOK b2
| _                                                             ->  false   

任务是定义一个带probability tree的函数(见下文),并检查它是否满足每个概率p0 <= p <= 1probability tree的类型为

type ProbTree = | Branch of string * float * ProbTree * ProbTree
                | Leaf of string

probability tree的含义是表示顺序过程的样本空间的树,其中过程中每个阶段的结果是成功还是失败。

一个probability tree的示例,其中掷出了六边骰子,并且>2 2/3的概率为<= 2,概率为1/3 { {1}}为let test = Branch(">2",0.67, Branch(">3",0.5, Leaf "A", Leaf "B") , Branch(">3",0.5, Leaf "C", Leaf "D")) ,依此类推:

Probability tree

在我的例子中,我正在研究的概率树是:

p

将返回true,因为所有概率([],Leaf _ )-> true都在0和1之内。

现在,我已定义的功能有效,但我觉得模式匹配可以简化,也许是通过做类似于let rec probOK = function | Branch(ds, p, b1, b2) when p <= 1.0 && p >= 0.0 -> probOK b1 && probOK b2 | Leaf _ -> true | _ -> false 的操作,但我无法弄明白。

任何提示?

EDIT1:缩短的建议(现在空格较少):

--no-extract-licenses

1 个答案:

答案 0 :(得分:4)

您可以通过分离遍历树节点来对其进行操作来简化代码。这是一个检查节点是否有效的函数:

let nodeProbOk = function
| Branch(_, p, _, _)-> p <= 1.0 && p >= 0.0
| Leaf _ -> true

这是一个测试所有节点都满足谓词的函数:

let rec forAllNodes pred = function
| Branch(_, _, a, b) as branch -> pred branch && forAllNodes pred a && forAllNodes pred b
| Leaf _ as leaf               -> pred leaf

这就是你如何一起使用它们的方式:

test |> forAllNodes nodeProbOk

这种方法的优点是你有两个相对简单的函数,你可以将forAllNodes重用于验证以外的目的。这限制了在代码中使用递归所需的位置数量,并且应该更容易推理。