2014-02-06 4 views
7

Я пытаюсь сопоставить все вхождения регулярного выражения и получить индексы в результате. Пример из Real World Haskell говорит, что я могу сделатьИндексы всех совпадений регулярного выражения

string =~ regex :: [(Int, Int)] 

Однако это нарушается, поскольку регулярное выражение библиотека была обновлена ​​с момента публикации RWH. (См. All matches of regex in Haskell и "=~" raise "No instance for (RegexContext Regex [Char] [String])"). Каков правильный способ сделать это?

Update:

Я нашел matchAll, которые могли бы дать мне то, что я хочу. Однако я понятия не имею, как его использовать.

ответ

4

Ключ к использованию matchAll использует аннотацию типа :: Regex при создании regexs:

import Text.Regex 
import Text.Regex.Base 

re = makeRegex "[^aeiou]" :: Regex 
test = matchAll re "the quick brown fox" 

Это возвращает список массивов. Для того, чтобы получить список (смещение, длина) пар, только доступ к первому элементу из каждого массива:

import Data.Array ((!)) 

matches = map (!0) $ matchAll re "the quick brown fox" 
-- [(0,1),(1,1),(3,1),(4,1),(7,1),(8,1),(9,1),(10,1),(11,1),(13,1),(14,1),(15,1),(16,1),(18,1)] 

Чтобы использовать оператор =~, все может измениться после RWH. Вы должны использовать предопределенные типы MatchOffset и MatchLength и специальный конструктор типа AllMatches:

import Text.Regex.Posix 

re = "[^aeiou]" 
text = "the quick brown fox" 

test1 = text =~ re :: Bool 
    -- True 

test2 = text =~ re :: String 
    -- "t" 

test3 = text =~ re :: (MatchOffset,MatchLength) 
    -- (0,1) 

test4 = text =~ re :: AllMatches [] (MatchOffset, MatchLength) 
    -- (not showable) 

test4' = getAllMatches $ (text =~ re :: AllMatches [] (MatchOffset, MatchLength)) 
    -- [(0,1),(1,1),(3,1),(4,1),(7,1),(8,1),(9,1),(10,1),(11,1),(13,1),(14,1),(15,1),(16,1),(18,1)] 

смотрите документацию для Text.Regex.Base.Context для получения более подробной информации о том, что контексты доступны.

UPDATE: Я считаю, что конструктор типа AllMatches был введен для разрешения неоднозначности введен, когда регулярное выражение имеет подвыражения - например:

foo = "axx ayy" =~ "a(.)([^a])" 

test1 = getAllMatches $ (foo :: AllMatches [] (MatchOffset, MatchLength)) 
    -- [(0,3),(3,3)] 
    -- returns the locations of "axx" and "ayy" but no subexpression info 

test2 = foo :: MatchArray 
    -- array (0,2) [(0,(0,3)),(1,(1,1)),(2,(2,1))] 
    -- returns only the match with "axx" 

Оба, по существу, список пар смещения длины, но они означают разные вещи.

+0

"typecast :: Regex" не относится к типу. Существует не изменение времени выполнения типа данных. Это аннотация типа – Squidly

+1

да - это лучший способ описать ее. – ErikR

Смежные вопросы