Haskell / GHC: matching multiple unary constructors with the same pattern

So, I played with the definition of the TrieSet data type (although I know I do not need it ):

module Temp where import Data.Map data TrieSet a = Nonterminal (Data.Map a (TrieSet a)) | Terminal (Data.Map a (TrieSet a)) insert :: Ord a => [a] -> TrieSet a -> TrieSet a insert [] (_ m) = Terminal m insert (a:as) (cm) = c $ insertWith (insert as . flip const) a (insert as $ Nonterminal empty) m 

When I received an error that I had never seen before:

 % ghc -c Temp.hs Temp.hs:8:11: Parse error in pattern 

So, it seems that the GHC does not like to map multiple unary constructors to the same template. I did another test to make sure this is a problem:

 module Temp2 where extract :: Either String String -> String extract (_ s) = s 

Which seemed to confirm my suspicion:

 % ghc -c Temp2.hs Temp2.hs:4:9: Parse error in pattern 

So my question (in several parts):

  • Am I right why the GHC does not like these features?
  • Any reason why this will not be part of the Haskell standard? In the end, we can map multiple constructors to the same template.
  • Is there a LANGUAGE pragma that I can give the GHC to accept?
+4
source share
2 answers
  • Yes. Such masks were not supported.
  • In my opinion, it would be much more difficult to deduce the type of the function if you do not know which data constructor was mapped. Just think of the function f (_ n) = n . What should be its type? The Haskell type system cannot describe the arity of type constructors, so a function of type f cannot exist.
  • I do not think so.
+9
source

If it makes sense to map two or more constructors to a wildcard pattern, it probably makes sense to combine these constructors and use an extra enumerated value to distinguish between them.

For instance:

 data Terminality = Terminal | Nonterminal data TrieSet a = Node Terminality (Data.Map a (TrieSet a)) foo :: TrieSet X -> X foo (Node _ m) = ... 

If you do not want to make this change to an existing data type, you can instead define a helper type and the corresponding helper function and perform the conversion before matching with the pattern.

 data TreeSetView a = Node Terminality (Data.Map a (TrieSet a)) view :: TrieSet a => TreeSetView a view (Terminal m) = TreeSetView TerminalityTerminal m view (Nonterminal m) = TreeSetView TerminalityNonterminal m 
+8
source

All Articles