重构F#函数以使用正向管道运算符

时间:2011-09-09 10:32:37

标签: .net f# functional-programming

type Range = int * int
type Domain = Range array

type Gene = int
type Individual = Gene array
type Population = Individual array

let genPop (domain:Domain) popSize =
  let genInd (domain:Domain) : Individual =
    let genGene (range:Range) = genNum (fst range) (snd range)
    Array.map genGene domain
  Array.init popSize (fun _ -> genInd domain)

因此,Population只不过是Individual的数组。每个Individual由一个Gene数组组成,它们只不过是整数的别名。 genNum只会为我们生成一个随机整数。

我对genPop实施不是特别满意。虽然它工作正常并且符合预期,但我想尝试一种使用正向管道运算符|>的实现,而不是那些子函数。

有关如何继续这方面的任何提示?理想情况下,我会说,人们可以从popSize开始,这将转变为一个人口,其成员是由基因组成的个体。问题是我们通常需要以相反的方式做事。我们首先需要创建基因,然后创建个体,然后才能创建人口!

你将如何实现这一点(除了我这样做的方式)?也许还有其他方法对我来说不明显?

3 个答案:

答案 0 :(得分:5)

fstsnd替换为模式匹配:

let genGene (x, y) = genNum x y

您的整个功能可以变为:

let genPop domain popSize =
  Array.init popSize (fun _ -> Array.map (fun (x, y) -> genNum x y) domain)

或:

let genPop domain popSize =
  [|for _ in 1..popSize ->
      [|for x, y in domain ->
          genNum x y|]|]

答案 1 :(得分:1)

该功能可以简化为(使用管道):

let uncurry f = fun(a,b) -> f a b //Helper function

let genPop (domain:Domain) popSize : Population  =
  (fun _ -> domain)
  |> Array.init popSize 
  |> Array.map ((uncurry genNum) |> Array.map)

答案 2 :(得分:1)

这是我的(第二次)尝试:

let genPop (domain : Domain) popSize : Individual [] =
    (fun _ ->
    domain
    |> Array.map (fun (a, b) -> genNum a b))
    |> Array.init popSize
    |> Array.map (Array.copy)