![](/img/trans.png)
[英]Can a function operating upon mutable data structure be referentially transparent?
[英]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.