Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using regexp in haskell function guards

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
like image 233
Quyk Avatar asked Aug 01 '15 18:08

Quyk


1 Answers

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.

like image 65
chi Avatar answered Oct 20 '22 00:10

chi