bloom/Main.hs

56 lines
1.4 KiB
Haskell

{-# language TypeApplications #-}
{-# language DataKinds #-}
{-# language LambdaCase #-}
{-# options_ghc -Wall -Werror #-}
module Main (main) where
import GHC.Exts (IsList(..))
import Data.Foldable (traverse_)
import System.Exit (ExitCode(ExitSuccess, ExitFailure), exitWith)
import Bloom (Bloom)
import qualified Bloom
import qualified Data.Binary as Binary
import qualified Data.ByteString.Lazy as ByteString
import System.Directory
import System.FilePath
import System.Environment
import Control.Monad (guard)
main :: IO ()
main = do
b <- cachedLoad
input <- lines <$> getContents
let ws' = filter (not . (`Bloom.elem` b)) input
traverse_ putStrLn ws'
exitWith (if null ws' then ExitSuccess else ExitFailure 1)
cachedLoad :: IO (Bloom Size String)
cachedLoad = do
cache <- getCachePath
load cache >>= \case
Nothing -> do
b <- build
ByteString.writeFile cache $ Binary.encode b
pure b
Just a -> pure a
getCachePath :: IO FilePath
getCachePath = (</> "bloom-spell/words.bin") <$> getEnv "XDG_DATA_HOME"
load :: FilePath -> IO (Maybe (Bloom Size String))
load p = do
cacheExists <- doesFileExist p
guard cacheExists
s <- ByteString.readFile p
case Binary.decodeOrFail @(Bloom Size _) s of
Left{} -> pure Nothing
Right (_, _, a) -> pure $ pure a
build :: IO (Bloom Size String)
build = fromList @(Bloom Size _) . lines <$> readFile dict
type Size = 0xffff0
dict :: FilePath
dict = "/usr/share/dict/words"