Rus*_*tam 5 generics f# pipeline
我无法理解为什么会这样
let data =
JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>>(
File.ReadAllText <| Path.Combine(myPath, "ejv.json"))
Run Code Online (Sandbox Code Playgroud)
没关系,而这个
let data =
JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>>
<| File.ReadAllText
<| Path.Combine(myPath, "ejv.json")
Run Code Online (Sandbox Code Playgroud)
给我两个错误,首先是:

第二是:

我做错了什么?
UPDATE @PatrykĆwiek提出了一个很好的编辑,它似乎修复了类型的错误:
let data = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>>
<< File.ReadAllText
<| Path.Combine(myPath, "ejv.json")
Run Code Online (Sandbox Code Playgroud)
但它产生了另一个令人费解的消息:意外的类型参数.这是一个截图:

我可以很容易地删除它删除<Dictionary<string, Dictionary<string, string>>>但在这种情况下我的数据是object类型,而不是Dictionary.我可以以某种方式保存类型信息使用流水线吗?
解
感谢@PatrykĆwiek解决方案如下:
let d<'a>(s:string) = JsonConvert.DeserializeObject<'a>(s)
let data =
Path.Combine(myPath, "ejv.json")
|> File.ReadAllText
|> d<Dictionary<string, Dictionary<string, string>>> with
Run Code Online (Sandbox Code Playgroud)
我不知道为什么,但没有别名d它不起作用.
据我所知,评估从左到右,所以你的第二个表达式相当于:
let data =
(JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>> <| File.ReadAllText)
<| Path.Combine(myPath, "ejv.json")
Run Code Online (Sandbox Code Playgroud)
注意操作如何流动.这意味着你将函数传递给DeserializeObject第一个,可能不是你想要做的.
当你这样做:
let data =
JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>>
<| (File.ReadAllText <| Path.Combine(myPath, "ejv.json"))
Run Code Online (Sandbox Code Playgroud)
它会工作.这相当于你的第一选择.
其他解决方案是反转管道以使数据流更自然:
let data = Path.Combine(myPath, "ejv.json")
|> File.ReadAllText
|> JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>>
Run Code Online (Sandbox Code Playgroud)
我忽略了一个选项,这不常用.您也可以使用函数组合运算符<<使其工作:
let data = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>>
<< File.ReadAllText
<| Path.Combine(myPath, "ejv.json")
Run Code Online (Sandbox Code Playgroud)
它基本上结合DeserializeObject : string -> 'a并ReadAllText : string -> string进入(在上面的例子中未命名)函数f : string -> 'a,其中f(s) = DeserializeObject(ReadAllText(s)).然后它将Path.Combinevia管道的结果输入f.