problem A: recomputing LLR
- fragment extraction takes as input: a sentence selection, data selection, and LLR
- data selection takes as input: sentence selection and LLR
- NEW: after data selection, we can recompute LLR (call it LLR2) - LLR2 takes data selection as input. There are two different ways of recomputing LLR
- What is effect of the LLR method on fragment extraction?
Solution: add a new LLRMethod argument to fragment extraction. Fragment extraction now takes three arguments. Furthermore, in computing the LLR, my fragment extraction function just passes in the data selection method it received in its parameters list.
data LlrMethod = LlrNoRecompute | LlrRecomputeDoc | LlrRecomputeSent
Problem B: decoupling token alignment
- NEW: we want to change fragment extraction by separating an implicit token alignment step from it. Fragment extraction would no longer take a sentence/data dir, but a token dir
- Token alignment depends on data selection, and LLR method...
- There is more than one way to do token alignment
Solution B: add a TokenAlignmentMethod argument to fragment extraction. Instead of passing in a sentence directory and data directory, I pass in a token aligned directory computed off the arguments passed to fragment extraction.
Here's what fragment extraction looks like now:
fragmentExtraction :: SentSelMethod -> DataSelMethod -> LlrMethod -> TokenAlignmentMethod -> ExactTarget
fragmentExtraction sm dm lm tm = ExactTarget path "" $ \ RedoArgs { rname } -> do
redoIfChange [ tokenDir, llrDir ]
createDirectoryIfMissing True rname
runMyIO "detect-fragments" $ [ tokenDir, llrDir </> "lexicon", rname ] ++ parallelRTS
recurseStampExt rname [ extEnChoice, extDataPerSentence ]
where
path = d_FRAGMENTS </> showPC sm </> showPC dm </> showPC lm </> showPC tm
tokenDir = ePath (tokenAlignment sm dm lm tm)
llrDir = llr2Dir sm dm lm
Bonus to Solution B: I had forgotten that after fragment extraction comes a "peers directory" step. Thanks to the Haskell type checker, I remember that I also need to extend the peers directory step with a token alignment method argument.
Before using my makedo library, I was trying to manage all this argument passing by deconstructing paths using basename and dirname. Crazy! Way way better to write your build files in a language that (A) has a notion of sum types or at least Enum types (B) lets you create your own types with minimal fuss (eg. I don't need a separate file per type, just declare them) and (C) statically type checks. To be honest, the language for this probably does not need to be Haskell. Even Java could do the job, although I think creating different enumerations like LLRMethod vs TokenAlignmentMethod might be more of a pain. The advantage to using Haskell over Java (aside from the usual higher order functions, etc) is the HSH library, I think. Maybe if there was a convenient way to write shell-script-like things in Java it could work.
But Bash or Perl script? No way!
We missed the deadline for our paper by the way, probably because I was spending so much initial time working on makedo. But I still think it was the right thing to do. I would not have been able to understand what I'm working on as well as I could have if I was still wading knee deep in shell script. Sometimes you just need to step aside and go abstract away some nonsense before you get to the meat of your job. I hope that if we don't get a paper out of this, I can at least release my makedo library, and that somebody else benefits from it.
Take home message:
Statically typed shell scripts and Makefiles are good for you.

