设计用于从通道读取的引用透明函数
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 无所谓),但我看不出它有什么帮助(我们需要相同的 mock
的 SeekableByteChannel
,但现在包含在 IO
) 中。
你能帮我用纯 FP 风格设计这个函数吗(或者至少让它不那么难看)?
当你需要包装不纯的代码时,大多数时候(根据我的经验),它不会 "be pretty"。但是,我们得到的是我们只有一个处理 "messy stuff" 的点,我们从那里得到了一个很好的抽象。
我们想要的是创建一个由 IO
效果绑定的流。我们实际上处于 Stream[IO, 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 的原因,并从此时开始对流应用转换。
我试图坚持纯 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 无所谓),但我看不出它有什么帮助(我们需要相同的 mock
的 SeekableByteChannel
,但现在包含在 IO
) 中。
你能帮我用纯 FP 风格设计这个函数吗(或者至少让它不那么难看)?
当你需要包装不纯的代码时,大多数时候(根据我的经验),它不会 "be pretty"。但是,我们得到的是我们只有一个处理 "messy stuff" 的点,我们从那里得到了一个很好的抽象。
我们想要的是创建一个由 IO
效果绑定的流。我们实际上处于 Stream[IO, 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 的原因,并从此时开始对流应用转换。