设计用于从通道读取的引用透明功能



我试图坚持纯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 无关紧要(,但我看不出它有什么帮助(我们需要相同的SeekableByteChannelmock,但现在包装成IO(。

你能帮我以纯FP风格设计这个功能(或者至少让它不那么丑陋(吗?

当你需要包装不纯的代码时,大多数时候(根据我的经验(,它不会"漂亮"。但是,我们得到的是,我们只有一个点来处理"混乱的东西",从那里我们得到了一个很好的抽象。

我们想要的是创建一个受IO效果约束的流。而不是Stream[Id, SeekableByteChannel],我们真的处于Stream[IO, 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 的原因,并从这一点开始对流应用转换。

相关内容

  • 没有找到相关文章

最新更新