Data.List为monad插入

时间:2019-12-01 13:35:37

标签: parsing haskell monads

我正在使用ReadP模块编写一个小型解析器。我有这个表情:

cmdExpr = string "create" <|> string "add" <|> string "another alias" <|> ...

我想抽象化<|>操作,但是我不知道如何操作。类似于intercalate

getExpr cmds = intercalateM (<|>) $ map string cmds
cmdExpr = getExpr ["create", "add", "another alias", ...]

有什么想法吗?

3 个答案:

答案 0 :(得分:6)

您可以使用choice

Prelude Text.ParserCombinators.ReadP> cmds = ["create", "add", "another alias"]
Prelude Text.ParserCombinators.ReadP> :t choice $ map string cmds
choice $ map string cmds :: ReadP String

答案 1 :(得分:4)

您需要的是折叠。

<|>不是列表元素,它是一个带有两个参数的关联函数。

您需要执行以下操作:

getExpr cmds = foldr1 (<|>) $ map string cmds

请注意,使用foldr1是一种快速而肮脏的解决方案:如果给定一个空列表,它将引发异常。健壮的方法是将foldr与某种空解析器一起用作基本情况。

答案 2 :(得分:1)

这是asumMap in Relude的完美用例:

getExpr cmds = asumMap string cmds
cmdExpr = getExpr ["create", "add", "another alias", ...]

如果您没有使用Relude,而是在使用其他第三方库,则还有其他相同的功能,例如altMap in Util

import Util (altMap)
getExpr cmds = altMap string cmds
cmdExpr = getExpr ["create", "add", "another alias", ...]

如果您想坚持使用Base,那么可以分别使用as David Fletcher mentioned in a commentasummap

import Data.Foldable (asum)
getExpr cmds = asum $ map string cmds
cmdExpr = getExpr ["create", "add", "another alias", ...]