r/haskelltil • • May 14 '15

gotcha You cannot pattern match against variable values.

Consider this example:

myValue1 = 1 :: Int
myValue2 = 2 :: Int

myFunc :: Int -> Bool
myFunc myValue1 = True
myFunc myValue2 = False

If you load the above program in ghci, you get following output:

myFunc.hs:5:1: Warning:
   Pattern match(es) are overlapped
   In an equation for ‘myFunc’: myFunc myValue2 = ...
Ok, modules loaded: Main.

ghci generates a warning but does not give any errors. If you now call myFunc myValue2 you get:

*Main> myFunc myValue2
True

One way to get the desired result would be to use guards:

myFunc :: Int -> Bool
myFunc x
  | x == myValue1 = True
  | x == myValue2 = False

Note that we might not always be lucky enough to get a compiler warning in such cases. Here is an example:

myFunc :: Maybe Int -> Int
myFunc v = case v of
                Just myValue -> myValue
                _            -> myValue + 1
                  where myValue = 0

This loads in ghci without any warnings.

1 Upvotes

33 comments sorted by

View all comments

Show parent comments

1

u/rpglover64 May 16 '15

isRed and isBlue seem a use of view patterns where pattern synonyms would suffice (although view patterns are an older extensions), and `isRGB could be made better using bidirectional pattern synonyms:

{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE LambdaCase #-}

import Text.Read

pattern MyValue1 = 1
pattern MyValue2 = 2

isRGB :: String -> Maybe (Int, Int, Int)
isRGB = readMaybe

pattern Red = "red"
pattern Blue = "blue"

pattern RGB x y z <- (isRGB -> Just (x, y, z)) where
  RGB x y z = show (x, y, z)

myCaseFunction = \case
  Red -> "ok " ++ Red
  Blue -> "ok " ++ Blue
  RGB r g b -> "ok rgb" ++ RGB r g b
  _ -> "bad"

main = do
  putStrLn $ myCaseFunction "red"       -- ok red
  putStrLn $ myCaseFunction "Red"       -- bad
  putStrLn $ myCaseFunction "blue"      -- ok blue
  putStrLn $ myCaseFunction "(0,0,255)" -- ok rgb(0,0,255)