56 lines
1.4 KiB
Haskell
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"
|