I've generated a list of assertions I'd like to have run.
Here's an interesting case. In the script below, a list of pairs of strings are generated with the entries in the pairs never being equal (namePairs
). An assertion should throw an error if one of the strings is a substring of the other string in the pair. I've played around with the script enough to notice that it will throw an error if you encounter foo
(which happens when head
is used, as shown), or an error will be shown if you replace head
with last
, but in this case it will occur for bar
- the last string in the list). But this only works if I leave off the i =/ j
guard, which is not what I want, but helped me to identify the issue. If the guard is left in, then no error is thrown since these cases were the cases where i == j
.
I saw How to force evaluation in Haskell?, but despite using the BangPatterns
approach described there, I've not been able to get this to work, despite the cargo-cult level of usage.
#!/usr/bin/env stack
{- stack script --nix --resolver lts-14.20
--nix-packages zlib
--no-nix-pure
--package non-empty-text
--package text
--package time
-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Main where
import Data.Maybe
import Data.List (isSubsequenceOf)
import Data.Text (Text)
import qualified Data.Text as DT
import qualified Data.Text.Lazy as DTL
import qualified Data.Text.IO as DTIO
entryKeys :: [Text]
entryKeys = filter (\t -> DT.length t > 0) $ DT.split (==' ')
"foo DIBBsMain DIBBsContainers DIBBs bar"
main :: IO ()
main = do
putStrLn $ show entryKeys
!_ <- entryNameCheck entryKeys
pure ()
entryNameCheck :: [Text] -> IO ()
entryNameCheck !eNames = do
putStrLn $ show namePairs
!x <- pure $ checkPair <$> namePairs
pure $ head x
where
!lStr = DT.unpack . DT.toLower
!namePairs = [(lStr i, lStr j) | i <- eNames, j <- eNames, i /= j]
errmsg !ns = "!! " <> fst ns <> " is a substring of " <> snd ns
checkPair !p = assertOrErr ((not $ isSubsequenceOf (fst p) (snd p))) (errmsg p)
assertOrErr :: Bool -> String -> ()
assertOrErr !cond !msg = if cond then () else error msg