packages feed

detrospector-0.2: Detrospector/Modes/Neolog.hs

{-# LANGUAGE
    NamedFieldPuns
  , BangPatterns #-}
module Detrospector.Modes.Neolog(neolog) where

import Detrospector.Types
import Detrospector.Modes

import Data.Char
import Control.Applicative
import qualified Data.HashSet      as HS
import qualified Data.Text.Lazy    as Txt
import qualified Data.Text.Lazy.IO as Txt

-- Generate neologisms.
go :: Mode -> Chain -> RNG -> IO ()
go Neolog{minLen,maxLen,wordFile} c@(Chain n _) g
  = getWords >>= loop where

  getWords = (HS.fromList . map (listToQueue . Txt.unpack) . Txt.lines)
    <$> Txt.readFile wordFile

  loop !wd = do
    xs  <- fmap toLower <$> make emptyQ emptyQ
    wdd <- if (qLength xs >= minLen) && not (HS.member xs wd)
      then putStrLn (queueToList xs) >> return (HS.insert xs wd)
      else return wd
    loop wdd

  make !xs !s | qLength xs >= maxLen = return xs
              | otherwise = do
      (x,h) <- pick c s g
      -- give up if we don't use all history
      if (h == qLength s) && isAlpha x
        then make (xs `qSnoc` x) (shift n x s)
        else return xs

go _ _ _ = error "impossible: wrong mode passed to neolog"

neolog :: ModeFun
neolog m@Neolog{chain} = withChain chain $ go m
neolog _ = error "impossible: wrong mode passed to neolog"