簡體   English   中英

設計參照透明功能以從通道讀取

[英]Designing referentially transparent function for reading from channel

我試圖堅持純FP風格,並希望設計一個參照透明功能。

我有一個java.nio.channels.SeekableByteChannel ,它是一個數據源。 打開文件並獲取SeekableFileChannel實例后,我需要讀取文件的第一行,並使用這些行確定查找位置。

因此,我創建了以下函數:

object AdjustChannelAndGetStream {

  def apply(ch: SeekableFileChannel)
           (firstChunksToOffset: List[Array[Byte]] => Long): fs2.Stream[Id, Array[Byte]] {
    val offset = //depending on the first bytes read from the file 
                 //get the number of bytes read before
    val newChannel = ch.position(offset)
    //finally wrap newChannel into fs2.Stream
  }
}

問題是,該函數看起來很丑。 它不會暫停副作用,這使其難以測試(模擬SeekableByteChannel )。

我傾向於將SeekableByteChannel包裝到IO[SeekableByteChannel] (Scalaz / Cats無關緊要),但是我看不到它有什么幫助(我們需要相同的SeekableByteChannel mock ,但現在包裝到IO )。

您能否幫助我以純FP樣式設計此功能(或至少使其不那么難看)?

當您需要包裝不純凈的代碼時,大多數時候(根據我的經驗),它不會變得“漂亮”。 但是,我們得到的是,只有一個點可以處理“混亂的東西”,並且從那里可以得到很好的抽象。

我們想要的是創建一個受IO效果約束的流。 實際上,我們位於Stream[IO, SeekableByteChannel] Stream[Id, SeekableByteChannel]而不是Stream[Id, SeekableByteChannel] ,因為我們處於IO效果上下文中:

import java.nio.channels.SeekableByteChannel
import cats.effect.IO

object AdjustChannelAndGetStream {
    def apply(ch: SeekableByteChannel)(
        firstChunksToOffset: List[Array[Byte]] => Long)
      : fs2.Stream[IO, SeekableByteChannel] = {
      fs2.Stream.eval {
        IO {
          val offset: Int = ???
          ch.position(offset)
        }
      }
    }
}

這樣,我們暫停了副作用,這就是我們想要進行這些副作用計算RT的過程,並從此開始對流應用轉換。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM