简体   繁体   English

Haskell相当于scala收集

[英]Haskell equivalent of scala collect

I'm trying to read in a file containing key/value pairs of the form: 我正在尝试读取包含表单的键/值对的文件:

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

With various other lines, as suggested. 如所建议的那样,有各种其他线路。 This wants to go into a map that I can then look up keys from. 这想要进入我可以从中查找键的地图。

My initial approach would be to read in the lines and split on the '=' character to get a [[String]] . 我最初的方法是读取行并在'='字符上拆分以获得[[String]] In Scala, I would then use collect , which takes a partial function (in this case something like \\x -> case x of a :: b :: _ -> (a,b) and applies it where it's defined, throwing away the values where the function is undefined. Does Haskell have any equivalent of this? 在Scala中,我会使用collect ,它接受一个部分函数(在这种情况下类似于\\x -> case x of a :: b :: _ -> (a,b)并将其应用于定义的地方,扔掉函数未定义的值.Haskell有没有相应的这个?

Failing that, how would one do this in Haskell, either along my lines or using a better approach? 如果不这样做,那么在Haskell中如何做到这一点,无论是沿着我的方向还是使用更好的方法?

Typically this is done with the Maybe type and catMaybes : 通常,这是使用Maybe类型和catMaybes

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

So if your parsing function has type: 所以如果你的解析函数有类型:

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

then you can build the map by parsing the input string into lines, validating each line and returning just the defined values: 然后,您可以通过将输入字符串解析为行来构建映射,验证每一行并仅返回定义的值:

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

where s is your input string. 其中s是您的输入字符串。

The List Monad provides what you are looking for. List Monad提供您正在寻找的东西。 This can probably be most easily leveraged via a list comprehension, although, it works with do notation as well. 这可能是通过列表理解最容易利用的,尽管它也适用于符号。

First, here's the Scala implementation for reference - 首先,这是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))

Now the list comprehension version using Haskell - 现在使用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")]

What's happening is that the pattern match condition is filtering out cases that don't match using the fail method from Monad . 发生的事情是模式匹配条件是使用Monadfail方法过滤掉不匹配的情况。

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

So both the list comprehension and do notation are leveraging fail , which desugars to this - 所以列表理解和做法都是利用fail ,这对此有所贬低 -

map (splitOn "=") xs >>= (
  \s -> case s of
    [k, v] -> return (k, v)
    _ -> fail ""
)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM