繁体   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