이전에 일련의 상태 전환으로 작성했을 프로그램을 재구성하는 방법을 이해하려고합니다.
몇 가지 비즈니스 논리가 있습니다.
type In = Long
type Count = Int
type Out = Count
type S = Map[Int, Count]
val inputToIn: String => Option[In]
= s => try Some(s.toLong) catch { case _ : Throwable => None }
def transition(in: In): S => (S, Out)
= s => { val n = s.getOrElse(in, 0); (s + (in -> n+1), n+1) }
val ZeroOut: Out = 0
val InitialState: S = Map.empty
이것들을 사용하여 초기 State (빈 Map)를 전달하고 stdin 에서 입력을 읽고으로 변환 In
하고 상태 전환을 실행하고 현재 상태 S
와 출력 Out
을 stdout으로 출력 하는 프로그램을 구성하고 싶습니다 .
이전에는 다음과 같이했을 것입니다.
val runOnce = StateT[IO, S, Out](s => IO.readLn.map(inputToIn) flatMap {
case None => IO((s, ZeroOut))
case Some(in) => val (t, o) = transition(in)(s)
IO.putStrLn(t.toString) |+| IO.putStrLn(o.toString) >| IO((t, o))
})
Stream.continually(runOnce).sequenceU.eval(InitialState)
그러나 저는이 접근 방식 (상태 전환 스트림)을 scalaz-stream 과 연결하는 방법을보기 위해 정말 고심하고 있습니다 . 나는 이것을 시작했다.
type Transition = S => (S, Out)
val NoTransition: Transition = s => (s, 0)
io.stdInLines.map(inputToIn).map(_.fold(NoTransition)(transition))
유형 : Process[Task, Transition]
. 나는 거기에서 어디로 가야할지 정말로 모른다.
- 어떻게 "전달"
InitialState
하고 프로그램을 실행하여S
각 단계 의 출력 을S
다음 단계의 입력 으로 스레딩 합니까? - 각 단계에서
S
및 의 값을 가져Out
와서 stdout으로 인쇄 하려면 어떻게해야합니까 (문자열로 변환 할 수 있다고 가정)?
단일 이해력을 사용하려고 할 때 비슷한 문제가 발생합니다.
for {
i <- Process.eval(Task.now(InitialState))
l <- io.stdInLines.map(inputToIn)
...
어떤 도움이라도 대단히 감사합니다!
이제 조금 더 나아갔습니다.
type In_ = (S, Option[In])
type Out_ = (S, Out)
val input: Process[Task, In_]
= for {
i <- Process.emit(InitialState)
o <- io.stdInLines.map(inputToIn)
} yield (i, o)
val prog =
input.pipe(process1.collect[In_, Out_]) {
case (s, Some(in)) => transition(in)(s)
}).to(io.stdOutLines.contramap[Out_](_.toString))
그때
prog.run.run
작동하지 않습니다. 상태가 스트림을 통해 스레드 되지 않는 것 같습니다 . 오히려 각 단계에서 초기 상태가 전달됩니다.
Paul Chiusano는 process1.scan
. 이제 이렇게합니다.
type In_ = In
type Out_ = (S, Out)
val InitialOut_ = (InitialState, ZeroOut)
val program =
io.stdInLines.collect(Function.unlift(inputToIn)).pipe(
process1.scan[In_, Out_](InitialOut_) {
case ((s, _), in) => transition(in)(s)
}).to(io.stdOutLines.contramap[Out_](_.shows))
여기에 문제가 있습니다.이 특정 예제에서 내 Out
유형은 monoid 이므로 ID를 사용하여 초기 상태를 만들 수 있지만 일반적으로 그렇지 않을 수 있습니다. 그럼 내가 뭘할까요? (사용할 수있을 Option
것 같지만 불필요한 것 같습니다.)