haskellsyntaxpattern-matchingpattern-synonyms

Haskell - Using a constant in pattern matching


Let's say I have the following code (text in <> is a shorthand, not actually part of the code):

data A = <something>
defaultA :: A
defaultA = <Really complicated expression of type A>

Now I want to have a function pattern match on defaultA, like this:

f defaultA = <case 1>
f _ = <case 2>

However, defaultA in the first line becomes a new variable, not a condition that means the parameter will equal defaultA. The best way I know to achieve something like what I want is:

f x | x == defaultA = <case 1>
f _ = <case 2>

Does anyone know a better way?


Solution

  • If the definiton of defaultA consists only of constructor calls, you could use a pattern synonym.

    {-# LANGUAGE PatternSynonyms #-}
    
    data A = A Int
    
    pattern DefaultA = A 3
    
    isDefaultA DefaultA = putStrLn "it was a default"
    isDefaultA _ = putStrLn "it was not a default"
    

    This isn't a particularly idiomatic deployment of PatternSynonyms though. I'd probably stick with Haskell 98, using a very-slightly-more-verbose guard clause with an equality test.

    data A = A Int deriving Eq
    
    defaultA = A 3
    
    isDefaultA a
        | a == defaultA = putStrLn "it was a default"
        | otherwise = putStrLn "it was not a default"
    

    Where pattern synonyms do come in useful is for wrapping up noisy library constructor calls imposed on you when you're doing datatype-generic programming with a pattern like free monads or Data Types a la Carte.

    {-# LANGUAGE PatternSynonyms #-}
    {-# LANGUAGE TypeOperators #-}
    
    -- fixed point of functor
    newtype Expr f = In (f (Expr f))
    
    -- functor coproduct
    data (f :+: g) a = Inl (f a) | Inr (g a)
    
    
    -- now plug in custom code
    data Add r = Add_ r r
    data Val r = Val_ Int
    type HuttonsRazor = Expr (Add :+: Val)
    
    pattern Add x y = In (Inl (Add_ x y))
    pattern Val x = In (Inr (Val_ x))
    
    eval :: HuttonsRazor -> Int
    eval (Add x y) = eval x + eval y
    eval (Val x) = x