Haskell getArgs更改数据类型

时间:2014-04-28 15:14:28

标签: regex haskell type-conversion

我正在尝试为Haskell模块构建一个main函数,该模块将从用户处获取正则表达式并在SimplifyRegExp函数中使用它,但这需要RegExp类型的输入:

data RegExp sy  = Empty                              
            | Epsilon                            
            | Literal   sy                       
            | Or        (RegExp sy) (RegExp sy)  
            | Then      (RegExp sy) (RegExp sy)  
            | Star      (RegExp sy)              
   deriving (Read, Eq)

我如何能够将字符串转换为RegExp类型?

如果我将程序加载到GHCi上,那么我可以直接调用该方法,如下所示:

*Language.HaLex.RegExp> simplifyRegExp(Star (Star a))
'a'*

但是我想这样做,所以我可以在命令提示符中只传递一个参数的程序,它会打印出类似下面的结果(当然没有工作):

main = do
  n <- getArgs $ head
  print (simplifyRegExp(n))

1 个答案:

答案 0 :(得分:2)

您可以为您的类型定义Read实例并使用

data RegEx sy = ...
              deriving Read

然后使用readMay

import Text.Read
...

main = do
  regexp <- (readMay . head) `fmap` getArgs
  case regexp of
   Just r -> ...
   Nothing -> putStrLn "Parse error!"

但这在两个方面有点脆弱。首先是read是部分功能!如果正则表达式生成错误,您的程序将会爆炸。其次,使用您的默认read实例强制您的正则表达式的内部表示形式到您的用户!如果这是一个严肃的项目,你最好做一些实际的解析。

幸运的是,Haskell有一些非常棒的解析库。一些最着名的包括parsecattoparsec

parsec解析器的示例可能是

import Text.Parsec
import Text.Parsec.String

import Control.Applicative

parseStar :: Parsec (RegExp Char)
parseStar = Star <$> (parseRe <* char '*')

parseLiteral :: Parsec (RegExp Char)
parseLiteral = Literal <$> noneOf "*()"

parseOr :: Parsec (RegExp Char)
parseOr = Or <$> parseRe <*> (char '|' *> parseRe)

parseThen :: Parsec (RegExp Char)
parseThen = Then <$> parseRe <*> parseRe

....