F# 用计算表达式追加多个列表
我有一个函数,它生成一些元素并在列表中返回它们。函数接受一个参数来过滤返回的元素。函数如下所示:F# 用计算表达式追加多个列表,f#,functional-programming,F#,Functional Programming,我有一个函数,它生成一些元素并在列表中返回它们。函数接受一个参数来过滤返回的元素。函数如下所示: let create x = [1..1000] |> List.filter (fun c -> (c % x) = 0) 现在我想用多个条件调用这个函数,并将所有结果附加到一个列表中 起初,我想这样做: let result = (create 100) |> List.append (create 300) |> L
let create x = [1..1000] |> List.filter (fun c -> (c % x) = 0)
现在我想用多个条件调用这个函数,并将所有结果附加到一个列表中
起初,我想这样做:
let result = (create 100)
|> List.append (create 300)
|> List.append (create 500)
|> List.append (create 3)
printf "%A" result
但是我发现这个解决方案在使用List.append
表达式时并不优雅和重复
我尝试了第二种解决方案:
let result = [100; 300; 500; 3] |> List.map (fun c -> create c)
|> List.reduce (fun acc c -> acc |> List.append c)
printf "%A" result
这个解决方案更简洁,但我不喜欢它。我发现它不那么清晰,更难猜测我们试图实现什么
因此,我正在寻找第三种解决方案,并尝试使用计算表达式实现一种新的解决方案:
type AppendBuilder() =
member this.Bind (x, f) = f x |> List.append x
member this.Return x = x
然后像这样使用它:
let append = new AppendBuilder()
let result = append {
let! a = create 100
let! b = create 300
let! c = create 500
let! d = create 3
return []
}
printf "%A" result
最后一个解决方案有效,我更喜欢它。我发现它更清晰,更容易理解我们在做什么,并且没有repetive List.append表达式。但还是有问题。我不喜欢return[]
部分,这似乎不自然,也不清楚。但要使其发挥作用,这一技巧是必要的
第三种解决方案是我最喜欢的,但我不确定这是解决我问题的正确方法。它解决了问题,我得到了正确的结果,但我不确定这是否是正确的方法
我能保留第三种解决方案而不引起对我意图的混淆吗?解决方案是否足够清晰,可以保持原样?我正在寻找一种更专注于操作的解决方案(这里调用
create x
),而不是寄生在代码中的重复表达式(这里调用List.append
)。您可以从seq
计算的惰性中获益:
seq {
yield! create 100
yield! create 300
yield! create 500
yield! create 3
} |> List.ofSeq
然后使用list.ofSeq计算列表如果第三个是您最喜欢的版本,那么您可能需要使用列表理解:
let result =
[ yield! create 100
yield! create 300
yield! create 500
yield! create 3 ]
值得注意的是:使用Python列表后,我确实发现它们更友好,因为您可以使用值1000
,而不是值1001
如果您的create
函数始终是step函数
,则使用List的内置功能更有意义。如果您计划使用一个create
函数,但该函数不能利用List的内置功能,那么注释by更有意义
let result =
[100;300;500;3]
|> List.collect create
注释中建议的一种变体是允许create
函数的值作为参数输入
let makeList parms =
parms
|> List.collect create
然后用作
let result = makeList [100;300;500;3]
甚至
由于这是作为答复提出的: 最简单的方法是使用
List.collect
,它可以在一个步骤中映射和组合列表
本例中的解决方案如下所示
[100;300;500;3] |> List.collect create
那我更喜欢@JohnPalmer的解决方案,而不是发布的所有答案。它充分利用了库函数,与所有已发布的解决方案相比,它允许参数(
[100;300;500;3]
)来自上一个计算步骤。是的,最好将您的计算表示为数据转换作为起点,如果有其他要求(例如性能),则从该角度出发感兴趣的是:并不是因为这个问题,而是因为重构功能代码的概念。
let makeList = List.collect create
[100;300;500;3] |> List.collect create