Как Вы раздаете значения объектов .NET в F#?

Я в настоящее время изучаю F# и функциональное программирование в целом (происхождения C#), и у меня есть вопрос об использовании объектов .net CLR во время моей обработки.

Лучший способ описать мою проблему будет состоять в том, чтобы дать пример:

let xml = new XmlDocument() 
            |> fun doc -> doc.Load("report.xml"); doc

let xsl = new XslCompiledTransform()
            |> fun doc -> doc.Load("report.xsl"); doc

let transformedXml = 
    new MemoryStream()
        |> fun mem -> xsl.Transform(xml.CreateNavigator(), null, mem); mem

Этот код преобразовывает XML-документ с использованием документа XSLT объекты .NET. Отметьте XslCompiledTransform. Загрузка работает над объектом и возвратами пусто. Также XslCompiledTransform. Преобразуйте требует объекта memorystream и возвращается пусто.

Вышеупомянутая используемая стратегия состоит в том, чтобы добавить объект в конце (; мадам), чтобы возвратить значение и заставить функциональное программирование работать.

Когда мы хотим сделать этого за другим, у нас есть функция на каждой строке с возвращаемым значением в конце:

let myFunc = 
  new XmlDocument("doc")
   |> fun a -> a.Load("report.xml"); a
   |> fun a -> a.AppendChild(new XmlElement("Happy")); a

Существует ли более корректный путь (с точки зрения функционального программирования) для обработки объектов .NET и объектов, которые были созданы в большем количестве среды OO?

Путем я возвратил значение в конце, затем имел подставляемые функции, везде чувствует немного как взлом а не корректный способ сделать это.

Любая справка значительно ценится!

7
задан Russell 8 March 2010 в 23:05
поделиться

2 ответа

Одним из больших преимуществ F # является то, что он позволяет смешивать стиль функционального программирования с другими стилями (а именно объектно-ориентированным и императивным). Поскольку большинство библиотек .NET являются объектно-ориентированными и императивными, лучший способ получить доступ к функциональным возможностям .NET из F # - это просто использовать императивные функции F #. Это означает, что при работе с объектами .NET идиоматический код F # будет выглядеть почти как C #.

РЕДАКТИРОВАТЬ : В следующем слегка измененном примере показано, как преобразовать XSL-преобразование в функцию, которая принимает имя входного файла и имя файла xsl.Он возвращает MemoryStream , в котором был записан результат:

let transformDocument inputFile xslFile =
  let doc = new XmlDocument()  
  doc.Load(inputFile)
  let xsl = new XslCompiledTransform() 
  xsl.Load(xslFile)

  let mem = new MemoryStream() 
  xsl.Transform(xml.CreateNavigator(), null, mem)
  mem

И второй пример:

let doc = new XmlDocument("doc")   
doc.Load("report.xml")
doc.AppendNode(new XmlElement("Happy"))

Это не означает, что вы каким-либо образом отказываетесь от функционального стиля - есть много возможностей использовать функциональный стиль при работе с .NET-классами. Например, вы можете использовать функции высшего порядка, такие как Seq.filter и Seq.map (или выражения последовательности), для обработки коллекций данных (или элементов XML). Вы по-прежнему можете писать абстракции, используя функции высшего порядка.

Пространство имен System.Xml очень важно, поэтому для функционального стиля мало места. Однако код, который генерирует данные, которые вы храните в XML, может быть полностью функциональным. Возможно, стоит взглянуть на классы LINQ to XML (в .NET 3.5+), потому что они разработаны в гораздо более удобной для функционального программирования манере (поскольку они должны хорошо работать с LINQ, который тоже работает).

10
ответ дан 6 December 2019 в 09:59
поделиться

Чтобы добавить еще один отличный совет к уже отличному ответу Томаса, есть возможность каррировать эти функции, чтобы дать хорошее представление о том, насколько полезен F #, даже с использованием императивного методы кодирования при необходимости.

В примере 1 Томас использовал преобразование xml-документа в xsl-документ:

let transformDocument inputFile xslFile =
  let doc = new XmlDocument()  
  doc.Load(inputFile)
  let xsl = new XslCompiledTransform() 
  xsl.Load(xslFile)

  let mem = new MemoryStream() 
  xsl.Transform(xml.CreateNavigator(), null, mem)
  mem

Прочитав этот пост, я подумал о том, как сделать еще один шаг и позволить нам каррировать эту функцию .Это означает (если мы выберем) мы можем передать функции только документ XSL, она вернет функцию, которая преобразует любой документ xml с заданным документом XSL:

let transform = 
    (fun xsl ->
        let xsl_doc = new XslCompiledTransform()
        xsl_doc.Load(string xsl)

        (fun xml -> 
            let doc = new XmlDocument() 
            doc.Load(string xml)
            let mem = new MemoryStream()
            xsl_doc.Transform(doc.CreateNavigator(), null, mem)
            mem
        )
    )

Таким образом, мы могли бы сделать следующее:

let transform_report_xsl = transform "report.xsl"
let transform_style_xsl = transform "style.xsl"

transform_report_xsl "report.xml"
transform_report_xsl "report2.xml"
transform_style_xsl "page.xml"
9
ответ дан 6 December 2019 в 09:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: