2013-03-26 2 views
14

Я пытаюсь прочитать в файле, содержащем пары ключ/значение вида:Haskell эквивалент Скале собирать

#A comment 
a=foo 
b=bar 
c=baz 
Some other stuff 

С различными другими линиями, как это было предложено. Это хочет перейти на карту, с которой я могу найти ключи.

Мой первоначальный подход состоял бы в том, чтобы читать строки и делиться символом '=', чтобы получить [[String]]. В Scala, я бы затем использовать collect, который принимает частичную функцию (в данном случае что-то вроде \x -> case x of a :: b :: _ -> (a,b) и применяет его там, где она определена, выбрасывая значения где неопределен функция. Есть ли у Haskell любой эквивалент этого?

в противном случае, как бы один сделать это в Haskell, либо вдоль моих линий или с использованием лучшего подхода

ответ

14

Обычно это делается с Maybe типа и catMaybes:

catMaybes :: [Maybe a] -> [a] 

Так что, если ваша функция синтаксического анализа имеет тип :

parse :: String -> Maybe (a,b) 

, то вы можете создать карту путем разбора входной строки в строки, проверки каждой строки и возвращает только определенные значения:

Map.fromList . catMaybes . map parse . lines $ s 

где s это ваш входной строки.

+15

нотабене 'catMaybes. map parse = mapMaybe parse', где 'mapMaybe' также из Data.Maybe. – dave4420

0

Список Monad предоставляет то, что вы ищете. Это, вероятно, легче всего использовать через понимание списка, хотя оно также работает с обозначениями.

Во-первых, вот реализация Scala для справки -

// Using .toList for simpler demonstration 
scala> val xs = scala.io.Source.fromFile("foo").getLines().toList 
List[String] = List(a=1, b=2, sdkfjhsdf, c=3, sdfkjhsdf, d=4) 

scala> xs.map(_.split('=')).collect { case Array(k, v) => (k, v) } 
List[(String, String)] = List((a,1), (b,2), (c,3), (d,4)) 

Теперь версия список понимание с помощью Haskell -

λ :m + Data.List.Split 
λ xs <- lines <$> readFile "foo" 
λ xs 
["a=1","b=2","sdkfjhsdf","c=3","sdfkjhsdf","d=4"] 

-- List comprehension 
λ [(k, v) | [k, v] <- map (splitOn "=") xs] 
[("a","1"),("b","2"),("c","3"),("d","4")] 

-- Do notation 
λ do { [k, v] <- map (splitOn "=") xs; return (k, v) } 
[("a","1"),("b","2"),("c","3"),("d","4")] 

Что происходит, что условие сравнения с шаблоном отфильтровывать случаи, что дон» t, используя метод fail от Monad.

λ fail "err" :: [a] 
[] 

Так как список понимание и сделать обозначения являются используя fail, которые desugars к этому -

map (splitOn "=") xs >>= (
    \s -> case s of 
    [k, v] -> return (k, v) 
    _ -> fail "" 
) 
Смежные вопросы