[英]Haskell equivalent of scala collect
我正在嘗試讀取包含表單的鍵/值對的文件:
#A comment
a=foo
b=bar
c=baz
Some other stuff
如所建議的那樣,有各種其他線路。 這想要進入我可以從中查找鍵的地圖。
我最初的方法是讀取行並在'='字符上拆分以獲得[[String]]
。 在Scala中,我會使用collect
,它接受一個部分函數(在這種情況下類似於\\x -> case x of a :: b :: _ -> (a,b)
並將其應用於定義的地方,扔掉函數未定義的值.Haskell有沒有相應的這個?
如果不這樣做,那么在Haskell中如何做到這一點,無論是沿着我的方向還是使用更好的方法?
通常,這是使用Maybe
類型和catMaybes
:
catMaybes :: [Maybe a] -> [a]
所以如果你的解析函數有類型:
parse :: String -> Maybe (a,b)
然后,您可以通過將輸入字符串解析為行來構建映射,驗證每一行並僅返回定義的值:
Map.fromList . catMaybes . map parse . lines $ s
其中s
是您的輸入字符串。
List 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")]
發生的事情是模式匹配條件是使用Monad
的fail
方法過濾掉不匹配的情況。
λ fail "err" :: [a]
[]
所以列表理解和做法都是利用fail
,這對此有所貶低 -
map (splitOn "=") xs >>= (
\s -> case s of
[k, v] -> return (k, v)
_ -> fail ""
)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.