Как оценивается этот рабочий процесс F #? - PullRequest
0 голосов
/ 01 февраля 2019

Я довольно новичок в F #, но читал о рабочих процессах и выражениях вычислений.Из прочитанного мною чтения мне показалось, что у меня есть хотя бы базовое понимание цели рабочего процесса и синтаксиса использования рабочего процесса.Затем я наткнулся на пример здесь: BitWorker Workflow .

Я попытался скопировать код примера в локальный проект и успешно запустил его.Я начал что-то менять и понимать, что делает код, но все еще не могу понять, как на самом деле работает этот рабочий процесс.Я не видел других примеров, где синтаксис рабочего процесса был бы таким: do bitWriter stream {... вместо do workflow {....

let stream = new IO.MemoryStream()

// write TCP headers
do bitWriter stream {
    do! BitWriter.WriteInt16(12345s)           // source port
    do! BitWriter.WriteInt16(12321s)           // destination port
    do! BitWriter.WriteInt32(1)                // sequence number
    do! BitWriter.WriteInt32(1)                // ack number
    do! BitWriter.WriteInt32(2, numBits = 4)   // data offset
    do! BitWriter.WriteInt32(0, numBits = 3)   // reserved
}

Я бы не ожидал, что stream станет частью bitWriterрабочий процесс.Что здесь означает использование stream для рабочего процесса?

1 Ответ

0 голосов
/ 01 февраля 2019

Это должно быть легче объяснить, если мы посмотрим на минимальный пример, который реализует рабочий процесс, подобный этому.Сначала я определю тип для операций, которые вы можете выполнять.Для простоты давайте выберем только одно:

type Operation =  
  | WriteInt32 of int

Типичные компиляторы вычислений F # не принимают никаких параметров конструктора, но вы можете на самом деле принимать параметры - компоновщик вычислений здесь принимает поток в качестве параметра и создает StreamWriter.В операции Bind аргумент является одним из наших значений Operation, и мы обрабатываем его, записывая значение в средство записи потока.Затем мы просто вызываем остальную часть вычисления, используя f ()

type BitWriter(stream:IO.Stream) = 
  let wr = new IO.StreamWriter(stream)
  member x.Bind(op, f) = 
    match op with
    | WriteInt32 i -> wr.Write(i)
    f ()
  member x.Zero() = ()
  member x.Run( () ) = wr.Dispose()

Операции Zero и Run не особенно интересны, но для перевода требуется Zero, а Run позволяетмы распоряжаемся писателем.Это не самый идиоматический способ определения выражений вычислений - он не следует монадической структуре - но на самом деле он работает!Два помощника, прежде чем мы сможем его использовать:

let writeInt32 i = WriteInt32 i
let bitWriter stream = BitWriter(stream)

И теперь вы можете написать код, в значительной степени похожий на то, что делает вышеуказанная библиотека:

let stream = new IO.MemoryStream()

bitWriter stream {
  do! writeInt32 1
  do! writeInt32 2
  do! writeInt32 3
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...