在F#中将相对简单的布尔函数写为Lambda表达式

时间:2017-05-11 22:39:58

标签: lambda f#

我使用F#创建了一个BST,包括一个count函数,该函数将通用布尔evaluate函数作为参数。这个evaluate函数告诉count哪个离开计数:例如,如果你想计算所有叶子,你会传递一个evaluate函数,如果叶子存在则返回true如果没有,则false

所有功能都按预期工作,但遇到了障碍。我需要创建一个evenCount函数来计算包含偶数值的所有叶子,我需要将它作为count的调用来实现,将lambda函数作为evaluate参数传递。但我无法弄清楚如何将一个函数转换成一个函数来测试整数是否为lambda表达式。

以下是基本功能/定义:

type BST =
| Empty
| TreeNode of int * BST * BST

let nodeTestBase = function
    | Empty -> false
    | _ -> true

let nodeTestEven = function
    | Empty -> false
    | TreeNode(value, left, right) ->
        if (value % 2 = 0) then true
        else false

let rec insert value tree =
    match tree with
    | Empty -> TreeNode(value, Empty, Empty)
    | TreeNode(hd, left, right) as node ->
        if hd = value then node
        elif value < hd then TreeNode(hd, insert value left, right)
        else TreeNode(hd, left, insert value right)

let count func tree =
    let rec loop tally = function
        | Empty -> tally
        | TreeNode(value, left, right) as node ->
            if func node then 1 + (loop 0 left) + (loop 0 right)
            else 0
    loop 0 tree

我需要在调用nodeTestEven时将整个count写为lambda表达式。即:

let evenCount = 
    count "lambda expression" tree_name

1 个答案:

答案 0 :(得分:1)

type BST =
| Empty
| TreeNode of int * BST * BST

let nodeTestBase = function
  | Empty -> false
  | _ -> true

let nodeTestEven = function
  | Empty -> false
  | TreeNode(value, left, right) ->
      if (value % 2 = 0) then true
      else false

let count f (t:BST) : int =
  let rec count f (t:BST) : int = 
    match t with
    | Empty -> 0                                                     // left or right could be empty (see case 3).
    | TreeNode(n,left,right) -> (if f n then 1 else 0) + (count f left) + (count f right)                // a leaf, so test and count.
    | TreeNode(_,left,right)  -> (count f left) + (count f right)    // count left and right branches
  count f t

let count2 f (t:BST) : int =
  let rec count f (t:BST) : int = 
    match t with
    | Empty -> 0                                                     // left or right could be empty (see case 3).
    // *** pass in predicate f : (BST -> bool) to decide
    // *** when to count the node. i.e. function takes a
    // ***  BST and returns a bool
    // see pattern matching docs on use of & https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/pattern-matching        
    | TreeNode(_,left,right) & x when f x -> 1 + (count f left) + (count f right)
    | TreeNode(_,left,right)  -> (count f left) + (count f right)    // count left and right branches
  count f t

测试数据

let t = TreeNode(1,
          TreeNode(2,
            TreeNode(10,
              TreeNode(12,Empty,Empty),
              TreeNode(14,Empty,Empty)),
            TreeNode(20,
              TreeNode(22,Empty,Empty),
              TreeNode(24,Empty,Empty))),
          TreeNode(5,
            TreeNode(3,Empty,Empty),
            TreeNode(7,Empty,Empty)
          ))

let even n = n % 2 = 0
let odd n = n % 2 = 1

<强>测试

预定义

count even t
count odd t

内联

count (fun n-> n%2=0) t
count (fun n-> n%2=1) t

整个节点

count2 nodeTestEven t

使用内联样式的整个节点

count2 (function 
        | Empty -> false 
        | TreeNode(value, left, right) -> (value % 2 = 0))
        t

使用有趣内联样式

测试整个节点
count2 (fun node->node |> function 
        | Empty -> false 
        | TreeNode(value, left, right) -> (value % 2 = 0))
        t

匹配版本

count2 (fun node->
          match node with
          | Empty -> false 
          | TreeNode(value, left, right) -> (value % 2 = 1)) 
       t