F# 将前向管道操作符语法转换为";正规的;功能组合
F#的第一步,所以这可能是网站中F#最基本的问题之一。在一个教程之后,我遇到了 当它使用F# 将前向管道操作符语法转换为";正规的;功能组合,f#,F#,F#的第一步,所以这可能是网站中F#最基本的问题之一。在一个教程之后,我遇到了 当它使用 //"Date,Open,High,Low,Close,Volume,Adj Close" let stockData = [ "2012-03-30,32.40,32.41,32.04,32.26,31749400,32.26"; "2012-03-29,32.06,32.19,31.81,32.12,37038500,32.12"; "2012-03-28,
//"Date,Open,High,Low,Close,Volume,Adj Close"
let stockData =
[
"2012-03-30,32.40,32.41,32.04,32.26,31749400,32.26";
"2012-03-29,32.06,32.19,31.81,32.12,37038500,32.12";
"2012-03-28,32.52,32.70,32.04,32.19,41344800,32.19";
"2012-03-27,32.65,32.70,32.40,32.52,36274900,32.52";
// And so on (don't even know now how to comment out in F#!)
]
let splitCommas (x:string) =
x.Split([|','|])
stockData
|> List.map splitCommas
|> List.maxBy (fun x -> abs(float x.[1] - float x.[4]))
|> (fun x -> x.[0])
作为描述的一部分,它说
最后,使用List.map和(fun x->x[0])的投影函数从最大行投影日期
因为我看不到List.map,所以我假设它使用了另一种语法,所以我尝试在没有Forward pipe操作符的情况下重写它,但我无法让它工作
List.map(fun x-> x.[0])
(List.maxBy(fun x -> abs(float x.[1] - float x.[4]))
List.map splitCommas stockData)
我犯了这个错误
stdin(54,18):错误FS0752:基于此程序点之前的信息,运算符“expr.[idx]”已用于不确定类型的对象。考虑添加其他类型约束
如果我试试这个
List.map(fun (x: string) x-> x.[0])
(List.maxBy(fun x -> abs(float x.[1] - float x.[4]))
List.map splitCommas stockData)
我明白了
stdin(71,26):错误FS0038:“x”在此模式中绑定两次
如果我把约束再次放在第二行,我发布的第一个错误
在这个很明显的问题上有什么帮助吗
谢谢
编辑:
使用第一个答案中给出的代码,我现在得到了这个错误
stdin(195,22):错误FS0001:此表达式应具有类型
字符串列表但这里有一种类型 字符串数组
据我所知,Lee和mattnewport的答案都是有意义的,并且都在同一条路径上,这就是为什么我不知道如何修复该错误。您传递给
列表的函数。map
有两个名为x
的参数,请删除第二个:
(fun (x: string) -> x.[0])
注意:您还需要为传递给列表的函数提供参数。maxBy
:
List.map(fun (x: string) -> x.[0])
(List.maxBy(fun (x: string array) -> abs(float x.[1] - float x.[4]))
(List.map splitCommas stockData))
传递给
List.map
的函数有两个名为x
的参数,请删除第二个:
(fun (x: string) -> x.[0])
注意:您还需要为传递给列表的函数提供参数。maxBy
:
List.map(fun (x: string) -> x.[0])
(List.maxBy(fun (x: string array) -> abs(float x.[1] - float x.[4]))
(List.map splitCommas stockData))
forward pipe操作符在F#中被大量使用的原因之一是,它有助于避免在尝试重新安排代码以使用正常函数调用语法时出现的类型推断问题。您对将字符串类型约束应用于x参数的想法是正确的,但是您在其中有一个额外的x,这将导致您的第二个错误 原始代码的描述似乎在某种程度上误导了您,因为它提到了此步骤中未使用的List.map。最后一个投影函数实际上只是从List.maxBy返回的字符串数组中选择第0个元素,它给出股票开盘价和收盘价之间最大绝对差值的日期。在投影函数中,x的类型为string[]而不是string:
> stockData
|> List.map splitCommas
|> List.maxBy (fun x -> abs(float x.[1] - float x.[4]))
val it : string [] =
[|"2012-03-13"; "32.24"; "32.69"; "32.15"; "32.67"; "48951700"; "32.67"|]
> it |> (fun x -> x.[0]);;
val it : string = "2012-03-13"
forward pipe操作符在F#中被大量使用的原因之一是,它有助于避免在尝试重新安排代码以使用正常函数调用语法时出现的类型推断问题。您对将字符串类型约束应用于x参数的想法是正确的,但是您在其中有一个额外的x,这将导致您的第二个错误 原始代码的描述似乎在某种程度上误导了您,因为它提到了此步骤中未使用的List.map。最后一个投影函数实际上只是从List.maxBy返回的字符串数组中选择第0个元素,它给出股票开盘价和收盘价之间最大绝对差值的日期。在投影函数中,x的类型为string[]而不是string:
> stockData
|> List.map splitCommas
|> List.maxBy (fun x -> abs(float x.[1] - float x.[4]))
val it : string [] =
[|"2012-03-13"; "32.24"; "32.69"; "32.15"; "32.67"; "48951700"; "32.67"|]
> it |> (fun x -> x.[0]);;
val it : string = "2012-03-13"
Wrt。问题标题:可以像这样机械地向前平移管道。当你看到
x |> f
你改写
f x
当有多个管道时,必须考虑它们与左侧关联,因此
x |> f |> g
真是
(x |> f) |> g
变成
g (f x)
现在我们可以机械地翻译原始示例,我们得到:
stockData
|> List.map splitCommas
|> List.maxBy (fun x -> abs(float x.[1] - float x.[4]))
|> (fun x -> x.[0])
==>
List.map splitCommas stockData
|> List.maxBy (fun x -> abs(float x.[1] - float x.[4]))
|> (fun x -> x.[0])
==>
List.maxBy (fun x -> abs(float x.[1] - float x.[4]))
(List.map splitCommas stockData)
|> (fun x -> x.[0])
==>
(fun x -> x.[0]) (List.maxBy (fun x -> abs(float x.[1] - float x.[4]))
(List.map splitCommas stockData))
然后我们可以折叠(funx->x[0])
,获得
(List.maxBy (fun x -> abs(float x.[1] - float x.[4]))
(List.map splitCommas stockData)).[0]
这说明了为什么我们有管道操作符:直截了当的语法很快变得很难理解。此外,尽管原始版本是完全可类型化的,但如果没有额外的类型注释,f#type democrator将无法键入该类型;见@mattnewport在其上述答案下的评论 Wrt。问题标题:可以像这样机械地向前平移管道。当你看到
x |> f
你改写
f x
当有多个管道时,必须考虑它们与左侧关联,因此
x |> f |> g
真是
(x |> f) |> g
变成
g (f x)
现在我们可以机械地翻译原始示例,我们得到:
stockData
|> List.map splitCommas
|> List.maxBy (fun x -> abs(float x.[1] - float x.[4]))
|> (fun x -> x.[0])
==>
List.map splitCommas stockData
|> List.maxBy (fun x -> abs(float x.[1] - float x.[4]))
|> (fun x -> x.[0])
==>
List.maxBy (fun x -> abs(float x.[1] - float x.[4]))
(List.map splitCommas stockData)
|> (fun x -> x.[0])
==>
(fun x -> x.[0]) (List.maxBy (fun x -> abs(float x.[1] - float x.[4]))
(List.map splitCommas stockData))
然后我们可以折叠(funx->x[0])
,获得
(List.maxBy (fun x -> abs(float x.[1] - float x.[4]))
(List.map splitCommas stockData)).[0]
这说明了为什么我们有管道操作符:直截了当的语法很快变得很难理解。此外,尽管原始版本是完全可类型化的,但如果没有额外的类型注释,f#type democrator将无法键入该类型;见@mattnewport在其上述答案下的评论 是的,李,我明白你的意思。语法一点也不流利。虽然我现在正在努力解决constraintsYes@Lee类型的问题,但我明白你的意思。语法一点也不流利。尽管我现在正在努力解决类型约束问题,但前向管道如何帮助避免类型推断问题?F#类型推断从左到右进行。如果我说
List.map(fun s->s.Length)[“abc”;“def”]
,那么我会得到一个错误,因为编译器在遇到lambda时无法推断s的类型。如果我说[“abc”;“def”]|>List.map(fun s->s.Length)
那么它可以正常工作,因为s的类型已经可以被推断为字符串。前向管道如何帮助避免类型推断问题?F#类型推断从左到右工作。如果我说List.map(fun s->s.Length)[“abc”;“def”]
,那么我会得到一个错误,因为编译器在遇到lambda时无法推断s的类型。如果我说[“abc”;“def”]|>List.map(fun s->s.Length)
,那么它可以正常工作,因为s的类型已经可以是b了