Haskell中列表中的模式匹配元素
假设我有以下类型,在其他地方定义了KType:
data PExpr =
PVal KType |
PCall String [PExpr]
我有一个功能:
tryReplace:: PExpr -> Maybe PExpr
出于我们的目的,请执行以下操作:
- 如果给定的PEXPR是PVAL,则无需返回
- ,如果给定的PEXPR是PCALL,并且是空的,并且是空的
- 如果给定的PEXPR是PCALL,则一无所获,并且完全由PVAL
- 返回(仅PEXPR)组成,如果给定的PEXPR是PCALL,并且在列表中具有PCALL,则列表中发现的第一个PCALL被全球定义的KType替换x。
到目前为止,这就是我完成1和2的方式:
tryReplace (PVal _) = Nothing
tryReplace (PCall _ []) = Nothing
我对实现#4时的#3保留版本不太确定:
tryReplace (PCall _ [PVal _]) = Nothing
tryReplace (PCall str (PVal x:xs)) = tryReplace (PCall str xs)
我本质上希望#4这样的模式匹配:
tryReplace (PCall str (PVal a:PVal b:...:PCall _:rest)) =
Just (PCall str (PVal a:PVal b:...:PVal newValue:rest))
“ ...”应该在找到PCALL之前代表所有PVAL。
我敢肯定,有一个功能可以做到与已经定义的非常相似的功能,但是无论我尝试实现自己的版本。
除非有一个单个模式函数匹配案例可以照顾#3,否则我无法想到#4工作的一种方法,因为我认为我会在穿越给定列表时被迫构建列表。但是,如果找到PCALL,则可能不会返回所构建的列表,这意味着一无所有。我应该怎么做?我应该定义另一个功能以帮助实施#4吗?
Let's say I have the following type, where KType is defined somewhere else:
data PExpr =
PVal KType |
PCall String [PExpr]
I have a function:
tryReplace:: PExpr -> Maybe PExpr
That for our purposes, does the following:
- Returns Nothing if the given PExpr is a PVal
- Returns Nothing if the given PExpr is a PCall and is empty
- Returns Nothing if the given PExpr is a PCall and is composed entirely of PVal
- Returns (Just PExpr) if the given PExpr is a PCall and has a PCall in the list, where the first PCall found in the list is replaced with a globally defined KType x.
So far, this is what I have in the way of accomplishing 1 and 2:
tryReplace (PVal _) = Nothing
tryReplace (PCall _ []) = Nothing
I am less sure about my version of #3 staying when #4 is implemented:
tryReplace (PCall _ [PVal _]) = Nothing
tryReplace (PCall str (PVal x:xs)) = tryReplace (PCall str xs)
I essentially want #4 to pattern match as such:
tryReplace (PCall str (PVal a:PVal b:...:PCall _:rest)) =
Just (PCall str (PVal a:PVal b:...:PVal newValue:rest))
"..." is supposed to represent all the PVal before a PCall is found.
I'm sure there's a function that does something very similar to this already defined, but regardless of that I am trying to implement my own version.
Unless there is a single pattern function match case that can take care of #3, I can't think of a way for #4 to work, as I think I would be forced to build a list while traversing the given list. But the list being built might not even be returned if a PCall is found, which means extra work was done for nothing. How should I go about this? Should I define another function to assist in implementing #4?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以使用一个附加功能,该功能将找出列表是否满足#3或#4,并相应地返回替代列表,
而不是
(bool,[pexpr])
,,只是[PEXPR]
可以为haspcall
实现,但这比这更凌乱。You can use an additional function that will find out if the list satisfies #3 or #4, and returns a substitute list accordingly
Instead of
(Bool, [PExpr])
,Just [PExpr]
can be implemented forhasPCall
but that would be messier than this one.让我们简化。假设您有一个项目列表,可以是
a
,b
,c
:我们可以添加布尔值以记住我们只有到目前为止看到
a
s:在这里我们使用
second @( - >)::(b - > c) - > (d,b) - > (d,c)
在结果元组的第二部分中添加a
:它将给我们:
借助 state monad 我们甚至可以隐藏输入
bool
get:给出相同的结果:
Lets simplify. Assume you have a list of items which can be one of
A
,B
,C
:We can add a Boolean to remember that we have only seen
A
s so far:Here we are using
second @(->) :: (b -> c) -> (d, b) -> (d, c)
to add anA
in the second part of the result tuple:Which will give us:
With the help of the state monad we can even hide the input
Bool
and get:Giving the same result: