我想在Haskell中定义一个语法,该语法匹配格式为" XY12XY"的字符串。 (一些alpha后跟一些数字),例如编程语言中的变量名。
customer123
是一个有效的变量名称,但是' 123客户'不是有效的变量名。
我不知道如何定义语法并编写验证函数来验证给定字符串是否是有效的变量名。我一直在尝试理解和调整解析器示例:https://wiki.haskell.org/GADT但我无法理解如何调整它以使其适合我的需要。
如果任何善良的Haskell大师会帮我定义这个:
validate :: ValidFormat -> String -> Bool
validate f [] = False
validate f s = ...
我想将ValidFormat语法定义为:
varNameFormat = Concat Alpha $ Concat Alpha Numeric
答案 0 :(得分:1)
我从一个简单的解析器开始,看看它是否满足您的需求,除非您能解释为什么这对您的用例来说还不够。解析器非常简单。我将用attoparsec:
给出一个非常简单(也许是不完整)的例子import Control.Applicative
import Data.Attoparsec.ByteString.Char8
import qualified Data.ByteString.Char8 as B
validateVar :: B.ByteString -> Bool
validateVar bstr = case parseOnly variableP bstr of
Right _ -> True
Left _ -> False
variableP :: Parser String
variableP =
(++)
<$> many1 letter_ascii -- must start with one or more letters
<*> many (digit <|> letter_ascii) -- then can have any combination of letters/digits
<* endOfInput -- make sure we don't ignore invalid trailing chars
variableP通过<*>
组合解析器,并要求您处理many1 letter_ascii
和many (digit <|> letter_ascii)
的结果。在这种情况下,我们只需通过(++)
连接两个结果,检查many1
,many
,letter_ascii
和digit
的类型。 <*
说&#34;解析这个,但丢弃右手解析器的结果&#34; (否则你必须处理3个结果)。
这意味着如果你在&#34; abc123&#34;上运行解析器你会回来&#34; abc123&#34;。如果你解析&#34; 1abc&#34;解析器将失败。
检查parseOnly的类型:
parseOnly :: Parser a -> ByteString -> Either String a
我们传递它的解析器和它应该解析的bytestring。如果解析器失败,我们将获得Left <something went wrong>
。如果解析器成功,我们将获得Right <our string>
。很酷的事情是...而不仅仅是在成功时给出一个字符串,我们可以使用variableP中的结果做任何事情,例如:使用与(++)
不同的东西,转换类型和诸如此类的东西(请注意解析器类型也可能必须改变。)
因为我们只关心解析器是否成功validateVar
,所以我们可以忽略两种情况下的结果。
因此,您只需定义解析器,而不是为您的语法定义GADT。
您可能还会发现此链接对于教程非常有用:http://www.seas.upenn.edu/~cis194/fall14/spring13/lectures.html(第10周和第11周,包括您基本上编写自己的小解析器库的作业)
答案 1 :(得分:0)
我是从examples of regex-applicative
取得的import Text.Regex.Applicative
import Data.Char
import Data.Maybe
varNameFormat :: RE Char String
varNameFormat = (:) <$> psym isAlpha <*> many (psym isAlphaNum)
validate :: RE Char String -> String -> Bool
validate re str = isJust $ str =~ re
你将
*Main> validate varNameFormat "a123"
True
*Main> validate varNameFormat "1a23"
False