管道运营商拒绝工作

时间:2013-12-25 10:59:57

标签: generics f# pipeline

我无法理解为什么会这样

let data = 
    JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>>(
         File.ReadAllText <| Path.Combine(myPath, "ejv.json"))

没关系,而这个

let data = 
    JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>> 
    <| File.ReadAllText
    <| Path.Combine(myPath, "ejv.json")

给我两个错误,首先是:

First error

,第二是:

Second error

我做错了什么?

更新@PatrykĆwiek提出了一个很好的编辑,似乎修复了类型错误:

let data = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>> 
       << File.ReadAllText 
       <| Path.Combine(myPath, "ejv.json")

但它产生了另一个令人费解的消息:意外的类型参数。 这是一个截图:

Unexpected type arguments.

我可以轻松删除<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 

我不知道为什么,但如果没有别名d它就不起作用。

1 个答案:

答案 0 :(得分:7)

据我所知,评价从左到右,所以你的第二个表达相当于:

let data = 
    (JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>> <| File.ReadAllText)
    <| Path.Combine(myPath, "ejv.json")

注意操作如何流动。这意味着你首先将一个函数传递给DeserializeObject,可能不是你想要做的。

执行此操作时:

let data = 
    JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>> 
    <| (File.ReadAllText <| Path.Combine(myPath, "ejv.json"))

它会起作用。这相当于你的第一个选择。

其他解决方案是反转管道以使数据更自然地流动:

let data = Path.Combine(myPath, "ejv.json") 
           |> File.ReadAllText 
           |> JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>>

修改

我忽略了一种选择,这种选择并不常用。您也可以使用函数组合运算符<<使其正常工作:

let data = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>> 
           << File.ReadAllText 
           <| Path.Combine(myPath, "ejv.json")

它基本上将DeserializeObject : string -> 'aReadAllText : string -> string合并为(上例中未命名)函数f : string -> 'a,其中f(s) = DeserializeObject(ReadAllText(s))。然后,它将Path.Combine的结果通过管道输入f