The State[S, ?]
models a stateful computation that receives a current state S
, and emits a new state S
along with
the payload.
We will use State
to try to account for the effect of symlinks in our file traversal. If we traverse a directory tree
that contains multiple symlinks to the same target file, we won't count the size of the target file more than once.
To do this we'll need to keep track if what files we've seen before. This is what requires the use of a State effect.
In this case, the state we'll be tracking (ie type S
) will be Set[FilePath]
- Note that
FilePath
now includes a new caseSymlink(path: String, linkTo: FilePath)
and theDefaultFilesystem
uses the File API to distinguish symlinks. Previously they were automatically followed.
-
Define an alias
_sym[R]
inEffTypes
to indicate thatState[Set[FilePath], ?]
is a member of effect stackR
-
Add the member constraint to
pathScan
andscanReport
-
We need to interpret the state effect in
main
. We'll use theevalStateZero[Set[FilePath]]
combinator. Eval here means that the final state isn't returned, just the computed payload. The zero suffix indicates that the zero value of aMonoid[Set[FilePath]]
in scope should be used as the initial state. That's coming in fromimports cats.implicits._
. The zero value of a set isSet.empty
. -
In
pathScan
, you'll should add a case to handleSymlink
. To read/write the current state use theget
/put
combinators, and/ormodify(f: S => S)
to run a state modification function. Your logic should check if the target of a symlink has been visited; if it has, then return an empty pathscan, while if it hasn't, add it to the visited set and invokepathScan
on the target.This is a tricky task. Remember to look at the solution for guidance if you get stuck.
- Run the test to check that symlinks are being handled.