复杂模式匹配

时间:2012-09-06 10:00:37

标签: haskell

haskell有可能匹配复杂的模式吗?

我的意思是,我有一个逗号分隔符值(CSV)文件:

name,ID,fieldA,fieldB

是否可以编写如下函数:

getName (n:',':xs) = n

其中n不是单个元素而是列表?

4 个答案:

答案 0 :(得分:6)

当我在20世纪80年代成为一个小男孩时,我实现了一种具有复杂模式的功能语言。它等于允许++模式。结果模式是模糊的,因此匹配涉及回溯搜索过程:程序员可以有效地指定是否最小化或最大化与++左边的模式匹配的前缀的长度。该语言具有“模式保护”的形式,因此可以测试候选匹配以查看后续计算是否成功并且在失败的情况下被拒绝。由此产生的程序通常在其意义上是明显的。这很有趣。

现在,遇到这些问题时,我会找到span,如果不能删除它,我会使用解析器组合器。

span :: (a -> Bool) -> [a] -> ([a], [a])
  

span,应用于谓词p和列表xs,返回一个元组,其中第一个元素是满足p的元素xs的最长前缀(可能为空),第二个元素是列表的其余部分

因此,特别是span (/= ',')会将String拆分为第一个逗号之前的任何内容(如果没有逗号,则为整个内容),其余的(如果有逗号则以逗号开头)一个)。

如果这不会削减它,我使用解析器组合器。

但我一直记得过去很容易。

答案 1 :(得分:3)

你应该编写一个函数来分割你的行...

import Data.List

parts = map tail . groupBy (/=) . (',':)

然后您可以轻松编写访问者功能:

getName xs = n where [n,_,_,_] = parts xs
getID   xs = i where [_,i,_,_] = parts xs
...

但是一如既往地使用数据类型会很好:

data Record = Record {getName :: String   
                     ,getId :: Int
                     ,getFieldA  
                     ,getFieldB :: String
                     } deriving Show 

initRecord xs = Record name (read id) fieldA fieldB where
                [name, id, fieldA, fieldB] = parts xs

当然,如果你需要处理错误,那就更难了......

顺便说一句,那里有一个Haskell CSV库:http://hackage.haskell.org/packages/archive/csv/0.1.1/doc/html/Text-CSV.html

答案 2 :(得分:2)

您可以使用splitOn中的Data.List.Split,然后使用列表元素上的模式匹配。

> splitOn "," "a,b,c,d"
["a","b","c","d"]

它在拆分包中。

对于更复杂的东西,你可以使用Parsec。

答案 3 :(得分:1)

嗯,我不确定,但我不这么认为。你可能应该在Haskell中查看一些关于regular expressions的内容,以便解决你的问题。