Hlint incorrectly flags patern matches as non exhaustive when using PatternSynonyms

I was looking for a way to alias the constructor types of the either keyword in order to avoid swapping right and left around, so while looking for things I could do I found the PatternSynonyms language feature, which functionally does exactly what I want it to do, but while checking out how it works in practice I noticed that when pattern matching on the aliased constructors the compiler and HLint both warn me that case ac is “non-exhaustive”. Is there a way around this? is this intended or a bug in how ghc flags warnings?

example code down below

{-# LANGUAGE PatternSynonyms #-}
module Main (main) where

type Result = Either

pattern Error :: e -> Either e a
pattern Error e = Left e

pattern Ok :: a -> Either e a
pattern Ok a = Right a

newtype NotDivisibleError = NotDivisibleError (Int, Int)

tryDiv :: Int -> Int -> Result NotDivisibleError Int
tryDiv a b
  | a `mod` b /= 0 = Error $ NotDivisibleError (a, b)
  | otherwise      = Ok $ a `div` b

main :: IO ()
main = do
  let ab = 12 `tryDiv` 6
  let ac = 12 `tryDiv` 5
  case ab of
    Left _ -> putStrLn "couldn't divide"
    Right r -> print r
  case ac of
    Error _ -> putStrLn "couldn't divide"
    Ok r -> print r

You need a {-# COMPLETE Error, Ok #-} pragma.

2 Likes

ty!, it works but I still wonder, is there a way that I could make this apply to any file importing the module, since if I putt the pattern decleration in a different module I have to add this pragma to every file that uses the synonym, thanks in advance.

I think that putting it in the source module makes it work on all the dependent modules, though I haven’t checked. You might want to change this to learn and mark @taylorfausak as correct.

1 Like

just tested it and it does work!, I have marked the thread accordingly