F# 将表达式树解析为嵌套列表

F# 将表达式树解析为嵌套列表,f#,expression-trees,F#,Expression Trees,我对F#比较陌生,在解析包含嵌套列表的表达式树时真的很费劲。从网上的点点滴滴,我拼凑了以下内容 我的标准类型定义为: type Return = | Real of float | Func of string * Return list 我对外部应用程序进行函数调用,该调用返回如下内容: val out : Return = Func ("List", [Func ("List",[Real 1.0; Real 2.0; R

我对F#比较陌生,在解析包含嵌套列表的表达式树时真的很费劲。从网上的点点滴滴,我拼凑了以下内容

我的标准类型定义为:

type Return = 
    | Real of float
    | Func of string * Return list
我对外部应用程序进行函数调用,该调用返回如下内容:

val out : Return =
    Func
        ("List",
             [Func ("List",[Real 1.0; Real 2.0; Real 3.0]);
              Func ("List",[Real 1.0; Real 2.0; Real 3.0]);
              Func ("List",[Real 1.0; Real 2.0; Real 3.0])])
我需要对其进行分析

[ [1.0; 2.0; 3.0] ; [1.0; 2.0; 3.0] ; [1.0; 2.0; 3.0] ]
我最初天真的想法是

let rec parse data =
    match data with
    | Real(y) -> y
    | Func("List", x) -> x |> List.map parse 
    | _ -> failwithf "Unrecognised"
但它在抱怨类型差异,我现在明白了

我的第二个想法是可能使用一些recursive List.fold(因为我可以折叠real列表并获得内部列表,但不知道如何在没有编译器抱怨类型的情况下将其推广到递归函数中)。超越我目前的智力火力

我的第三个想法是,也许我从外部应用程序获得的回报让这变得太困难了,因为在元组fst中没有关于元组snd中是什么的指示,除了它是一个“某物列表”这一事实之外

有这样一个问题:但它和我正在尝试的解决方案一样神秘


任何关于我追求哪一条道路的建议都将受到赞赏

有时,为正在实现的函数添加注释是很好的。然后,它会明确说明您正在尝试做什么:

type Return = 
    | Real of float
    | Func of string * Return list

let rec parse (data : Return) : float list =
    match data with
    | Real y ->  [ y ]
    | Func (_, returns) -> returns |> List.collect parse
    | _ -> failwithf "Unrecognised"

您的
x |>List.map parse
有一个类型
float List
,但在另一个分支上,您的表达式有一个类型
float
。您试图返回
浮动列表

您希望
解析
函数返回的对象类型是什么

如果您想要的输出是
[[1.0;2.0;3.0];[1.0;2.0;3.0];[1.0;2.0;3.0]
,那么您想要返回的似乎既不是
浮动列表
也不是
浮动列表
,而是一个任意嵌套的
浮动
列表

但这并不是一个标准类型,您需要自己将其定义为一个递归的有区别的联合(为了更好的实践,我们将使其通用):


谢谢,并注意到了类型注释。然而,在上面的示例中,我需要返回一个浮动列表,因为expressiontree嵌套深度为2。所以我需要
[[1.0;2.0;3.0];[1.0;2.0;3.0];[1.0;2.0;3.0]
而不是你的代码给出的
[1.0;2.0;3.0;1.0;2.0;3.0]
。当然,如果我得到的返回嵌套深度为3,我需要返回浮点列表。在这种情况下,我不会尝试编写递归函数,因为您只允许将特定形状的返回类型传递给您的函数,而对于其他情况,您只会抛出异常。如果您只想支持两个深度的表达式树,只需显式地对它们进行模式匹配即可。谢谢Bartek。很明显,我还没有对递归函数的含义有足够的了解,还不知道它们什么时候(不)有用。非常感谢。很明显,我仍然在以一种过于松散的方式思考类型,但这给了我所需要的结构。
type NestedList<'a> = 
    | Single of 'a
    | Collection of NestedList<'a> list
let rec parse = function
    | Real y ->  Single y
    | Func ("List", returns) -> Collection (returns |> List.map parse)
    | Func (l, _) -> failwithf "Unrecognised label %s" l