9

I would like to write a Haskell function that's behavior is dependent upon regex pattern matching one of the arguments. In a language like C/Python/Perl, I would definitely just use a large if/else construct, but I don't really have that option. What is the most idiomatic Haskell way to handle this?

I've considered guards, but they don't work: No instance for (Data.String.IsString source0):

function arg
  | arg =~ "pattern1" = dothis arg
  | arg =~ "pattern2" = dothat arg
  | otherwise = failwith arg

The pattern matching used in case constructs would be perfect, if it handled Regex.

function arg = case arg of
  (pattern1 match) -> dothis match
  (pattern2 match) -> dothat match
  _ -> failwith arg
1
  • in the version using gaurds, you probably need explicit type annotations, something like function :: String -> ReturnType Commented Aug 1, 2015 at 18:51

1 Answer 1

13

Your first example does work for me:

import Text.Regex.Posix

function :: String -> String
function arg
  | arg =~ "pattern1" = "1"
  | arg =~ "pattern2" = "2"
  | otherwise = "3"

I think your IsString error is due to the overloaded string literals extension. Try to disable that, or alternatively try to use explicit String strings:

function :: String -> String
function arg
  | arg =~ ("pattern1"::String) = "1"
  | arg =~ ("pattern2"::String) = "2"
  | otherwise = "3"

Too noisy? You can push the cruft to the last lines.

function2 :: String -> String
function2 arg
  | arg =~ s"pattern1" = "1"
  | arg =~ s"pattern2" = "2"
  | otherwise = "3"
  where s :: String -> String
        s = id

Need subgroup matching?

function3 :: String -> String
function3 arg
  | [_,x]:_ <- arg =~ s"pat(t*)ern1" = "matched group: " ++ x
  -- ...

On function3 "patttern1", variable x will be bound to "tt". On function3 "xyz", the test will fail and the next branch will be tried.

Sign up to request clarification or add additional context in comments.

3 Comments

PatternGuards are standard, no pragma needed. ViewPatterns might be even closer to what OP asks for, or the even more newfangled PatternSynonyms.
@matejcik Because the =~ has many overloads, including one returning list-of-lists, which I exploit here. I don't recall all the details, since I answered this 3 years ago, but the library docs should probably contain them.
Thank you for this answer, which was helpful! (Though for the function3 form I am always seeing that the first guard matches, even if the match is empty.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.