2

I'm writing some parse code over a tree. (Namely an Stanford nlp dependency tree)

Basically I have a function like this:

m :: DepTree -> Logic
m (w, [E "nsubj" nsubj, E "dobj" dobj]) = ...
m (w, [E "nsubj" nsubj, E "prep" prep]) = ...
m (w, [E "nsubj" nsubj]) = ...
m (_, []) = error "No rules apply"

What I want is to dispatch to the first rule if the node has an nsubj and a dobj edge coming out of it. I don't care about what else it might have.

Clearly my example function doesn't do this, since it requires the edges to be present in the right order, and it won't match if more edges are present.

One approach could be to use guards for more expressivity, I can do:

m (w, es) | (isJust.lookup "nsubj") es && (isJust.lookup "dobj") es = ...
          | ...
          | otherwise = error ...

But that's a lot more paintful, and I don't even get a handle on the target nodes.

Is there a standard way to write pattern matching parsers over graphs like mine? Or is there perhaps some magic based on the Maybe monad..?

Thomas Ahle
  • 30,774
  • 21
  • 92
  • 114

1 Answers1

6

You can use pattern guards:

{-# LANGUAGE PatternGuards #-}

m (w, es) | Just nsubj <- lookup "nsubj" es, Just dobj <- lookup "dobj" es = ...
          | ...
          | otherwise = error ...
dave4420
  • 46,404
  • 6
  • 118
  • 152
hammar
  • 138,522
  • 17
  • 304
  • 385
  • 3
    @dave4420: While it is probably good practice to include the pragma, pattern guards are standard since Haskell 2010 and thus enabled by default in GHC. – hammar Mar 15 '13 at 22:18
  • That I had not realised. My apologies. – dave4420 Mar 15 '13 at 22:26