Closed lawbel closed 7 months ago
I don't know much about TH. Is this possible?
I also don't know TH well enough to answer that 😅 I would think that if we can generate expressions, then surely (hopefully) we can use a similar approach to translate those expressions into a sensible pattern.
I imagine one should define quotePat
as well.
I've been working on this, but could do with some guidance on how best to proceed.
So this turns out to be a bit tricky actually, because of what is allowable as a valid pattern. We would need to either drill down into the underlying constructor and match against the payload, or use a view pattern to do some computation.
Using a view pattern is not ideal, because it forces the user to turn on ViewPatterns
. But otherwise it is simple to implement and it works.
Getting to the underlying constructor has proven difficult. I understand that OsPath
/OsString
is ultimately a wrapper around a ByteArray#
from base. But ByteArray#
is an abstract type that is not matchable on (correct me if I'm wrong?). So this seems to be impossible.
What do you think, go ahead with the view pattern approach?
On reflection, what we can do is define a pattern synonym (not certain whether it would have to exported to make this work):
pattern Packed :: [OsChar] -> OsPath
pattern Packed chars <- (System.OsPath.unpack -> chars)
where Packed chars = System.OsPath.pack chars
which hides the view pattern, and then can match on [OsChar]
as it's just a [Word8]
or a [Word16]
depending on platform. That seems like the best option.
I would expect [osp|foo|]
as a pattern to generate xs | xs == [osp|foo|]
. Is it not feasible?
@Bodigrim I would like to be be able to do that, but it turns out it isn't possible. If you look at QuasiQuoter you can see that quotePat
returns a Pat. There are various options for what sort of pattern a Pat
can be, such as
'c'
or 12
Constr pat1 pat2 pat3
(pat1, pat2)
But there is no option to add a pattern guard. I guess the reason is that the pattern we generate should be valid even if it's nested within some other pattern, but guards are only allowed at the top level.
@lawbel ah, I see. I think ViewP
is a solid option then: GHC would prompt user to enable ViewPatterns
.
Thanks @Bodigrim for all the help, I put together a PR which implements this as a view pattern.
I was quite surprised to find that the following code is not valid:
I can see that the
osp
QuasiQuoter is implemented to only support expressions, but this kind of use case feels very natural. Especially given that it is non-trivial to construct a validOsPath
literal.Is there any reason why this couldn't or shouldn't be implemented? If no, then I would be more than happy to have a go at it and put together a PR.