FSharpList <string>到IList <string>到XML </string> </string>

时间:2012-02-24 09:56:53

标签: c# f# c#-to-f#

使用代码将IList<T>转换为FSharpList<T>,然后将列表值写入XML。

public static class Interop
{
    public static FSharpList<T> ToFSharpList<T>(this IList<T> input)
    {
        return CreateFSharpList(input, 0);
    }

    private static FSharpList<T> CreateFSharpList<T>(IList<T> input, int index)
    {
        if(index >= input.Count)
        {
            return FSharpList<T>.Empty;
        }
        else
        {
            return FSharpList<T>.Cons(input[index], CreateFSharpList(input, index + 1));
        }
    }
}

我使用上面的代码制作我自己的列表

var fsharp_distinct = distinctWords.ToFSharpList();
var distinct_without_stopwords = Module2.stopword(fsharp_distinct);

foreach (string wd in distinct_without_stopwords)
    colwordfreq.Root.Add(new XElement(wd));

事实上,XML也是写的,但在退出循环之前,它给出了System.NullReferenceException。但是当一个F#函数使用相同的代码返回Tuple<string, int>时,我就没有问题将Tuple值写入XML。

编辑:我在上述问题中不正确。零点异常实际上来自此代码:

foreach (Tuple<string, int> pair in list2)
    colwordfreq.Root.Element(pair.Item1).Add(new XElement("freq", pair.Item2));

但是当我添加条件时

if (colwordfreq.Root.Element(pair.Item1) != null)

它没有给出那个例外。

1 个答案:

答案 0 :(得分:2)

您的示例有点不完整,但如果某些单词colwordfreq.Root.Element(pair.Item1)返回null,则可能表示您之前未添加该元素。也许你需要通过编写类似的东西来添加元素:

foreach (Tuple<string, int> pair in list2) 
  colwordfreq.Root.Add                                // Add element to the root
    (new XElement(pair.Item1,                         // with the name of the word
                  new XElement("freq", pair.Item2))); // ... and the count

除此之外,当您从C#调用F#代码时,值得查看F# component design guidelines。其中一个建议(我强烈建议遵循)是避免使用C#中的F#特定类型(如FSharpList)。这些都是为F#设计的,很难从C#中正确使用。

您可以添加一个简单的F#包装函数,使用IEnumerable公开该功能,这将更容易在C#中使用:

let rec stopword a = 
    match a with 
    |"the"::t |"this"::t -> stopword t 
    |h::t ->h::(stopword t) 
    |[] -> [] 

module Export = 
  let StopWord (inp:seq<_>) = 
    (inp |> List.ofSeq |> stopword) :> seq<_>

然后你可以从C#调用Export.StopWord(en)而不明确处理F#列表。